溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

NodeJS怎么實現同步

發(fā)布時間:2021-02-08 10:19:38 來源:億速云 閱讀:105 作者:小新 欄目:web開發(fā)

這篇文章主要介紹了NodeJS怎么實現同步,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

前言

眾所周知,異步是得天獨厚的特點和優(yōu)勢,但同時在程序中同步的需求(比如控制程序的執(zhí)行順序為:func1 -> func2 ->func3 )也是很常見的。

下面這篇文章主要介紹了關于NodeJS實現同步的相關內容,NodeJS被打上了單線程、非阻塞、事件驅動…..等標簽。 在單線程的情況下,是無法開啟子線程的。經過了很久的研究,發(fā)現并沒有thread函數?。。〉怯袝r候,我們確實需要“多線程”處理事務。nodeJS有兩個很基礎的api:setTimeout和setInterval。這兩個函數都能實現“異步”。 nodeJS的異步實現:nodeJS有一個任務隊列,在使用setInterval函數的時候,會每隔特定的時間向該任務隊列增加任務,從而實現“多任務”處理。但是,“特定的時間”不代表是具體的時間,也有可能是會大于我們設定的時間,也有可能小于。

我們跑跑下面代碼塊

setInterval(function() {
 console.log(new Date().getTime());
}, 1000);

輸出的結果如下:

1490531390640
1490531391654
1490531392660
1490531393665
1490531394670
1490531395670
1490531396672
1490531397675
......

我們可以看到,所有的時間間隔都是不一樣的。時間的偏移不僅包含了間隔的1s,還包含了console.log()的耗時,以及new Date()的耗時。在大量的數據統(tǒng)計下,時間間隔近似于1s。

問題來了,setInterval是能實現多任務的效果,但是怎樣才能實現任務之間的同步操作呢?

這里實現的方法是通過回調函數實現的。

function a(callback) {
 // 模擬任務a耗時
 setTimeout(function() {
  console.log("task a end!");
  // 回調任務b
  callback();
 }, 3000);
};

function b() {
 setTimeout(function() {
  console.log("task b end!");
 }, 5000);
}
a(b);

這里舉了一個很簡單的例子,就是將b方法的實現賦值給a方法的callback函數從而實現函數回調,但是會有個問題。假設a方法依賴于b方法,b方法依賴于c方法,c方法依賴于d方法…..也就意味著每個方法的實現都需要持有上一個方法的實例,從而實現回調。

function a(b, c, d) {
 console.log("hello a");
 b(c, d);
};

function b(c, d) {
 console.log("hello b");
 c(d);
};

function c(d) {
 console.log("hello c");
 d()
};

function d() {
 console.log("hello d");
};

a(b, c, d);

輸出結果

hello a
hello b
hello c
hello d

如果回調函數寫的多了,會造成代碼特別特別惡心。

如果有類似于sync的函數能讓任務順序執(zhí)行就更好了。終于找到了async這個庫 $ npm instanll async

async = require("async");
a = function (callback) {
 // 延遲5s模擬耗時操作
 setTimeout(function () {
  console.log("hello world a");
  // 回調給下一個函數
  callback(null, "function a");
 }, 5000);
};

b = function (callback) {
 // 延遲1s模擬耗時操作
 setTimeout(function () {
  console.log("hello world b");
  // 回調給下一個函數
  callback(null, "function b");
 }, 1000);
};

c = function (callback) {
 console.log("hello world c");
 // 回調給下一個函數
 callback(null, "function c");
};

// 根據b, a, c這樣的順序執(zhí)行
async.series([b, a, c], function (error, result) {
 console.log(result);
});

注釋基本能夠很好的理解了,我們看看輸出

hello world b
hello world a
hello world c
[ 'function b', 'function a', 'function c' ]

上面的基本async模塊的實現的如果了解更多關于async模塊的使用,可以點擊:查看詳情

其實nodeJS基本api也提供了異步實現同步的方式?;赑romise+then的實現

sleep = function (time) {
 return new Promise(function () {
  setTimeout(function () {
   console.log("end!");
  }, time);
 });
};

console.log(sleep(3000));

輸出結果為:

Promise { <pending> }
end!

可以看出來,這里返回了Promise對象,直接輸出Promise對象的時候,會輸出該對象的狀態(tài),只有三種:PENDING、FULFILLED、REJECTED。字面意思很好理解。也就是說Promise有可能能實現我們異步任務同步執(zhí)行的功能。我們先用Promise+then結合起來實現異步任務同步操作。

sleep = function () {
 return new Promise(function (resolve, reject) {
  setTimeout(function () {
   console.log("start!");
   resolve();
  }, 1000);
 })
  .then(function () {
   setTimeout(function () {
    console.log("end!");
   }, 2000);
  })
  .then(function () {
   console.log("end!!");
  })
};
console.log(sleep(1000));

輸出結果:

Promise { <pending> }
start!
end!!
end!

在new Promise任務執(zhí)行完后,調用了resolve才會執(zhí)行所有的then函數,并且這些then函數是異步執(zhí)行的。由輸出結果可以知道。(如果所有then是順序執(zhí)行的應該是end! -> end!!)。但是上述也做到了兩個異步任務之間順序執(zhí)行了。

不過,還有更加優(yōu)雅的方式:使用async+await。

display = function(time, string) {
 return new Promise(function (resovle, reject) {
  setTimeout(function () {
   console.log(string);
   resovle();
  }, time)
 });
};

// 執(zhí)行順序:b a c
fn = async function () {
 // 會造成阻塞
 await display(5000, "b");
 await display(3000, "a");
 await display(5000, "c");
}();

輸出結果:

b
a
c

由于這里時間輸出比較尷尬,只能通過我們來感知,本人通過個人“感知”知道了在display b過度到display a的時候大概用了3s,再過度到display c的時候大概用了5s

感謝你能夠認真閱讀完這篇文章,希望小編分享的“NodeJS怎么實現同步”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業(yè)資訊頻道,更多相關知識等著你來學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI