node 非同步程式設計

2022-02-25 08:54:30 字數 3438 閱讀 1137

我了解到的node非同步程式設計可分成: 

1.**函式 

2.pub/sub模式(發布/訂閱模式) 

3.promise 

4.generator 

5.async await

一.直接**函式

該方法是最直接常用的非同步操作方式,比如在setinterval 和 ajax等會使用到, 存在缺點有: 

1.**不易閱讀並且容易出現金字塔巢狀問題; 

2.一般只能對應乙個**函式(一對一),使用上有一定的限制;

fs.readfile('/etc/passwd', function (err, data) );

函式先讀取/etc/passwd,再執行**函式,在這兩者之間丟擲的錯誤會以引數形式傳入**函式中。

二.發布/訂閱模式

該方法不再侷限於一對一的形式,以多對多的形式監聽事件,可以很方便的訂閱和取消訂閱存在缺點有:需要借助類庫(jquery),事件與**函式的順序很重要。

三. promise

**函式的缺點之一是容易出現函式多層巢狀,難以維護的場面.而es6語法中的promise正好解決這類問題. promise包含三種狀態:pending、fulfilled、rejected,三種狀態只能發生兩種轉換(從pending—>fulfilled、pending—>rejected),並且狀態的轉換僅能發生一次。 

promise例項生成以後,可以用then方法分別指定resolved狀態和reject狀態的**函式: 

then方法可以接受兩個**函式作為引數。第乙個**函式是promise物件的狀態變為resolved時呼叫,第二個**函式是promise物件的狀態變為reject時呼叫。 

a) then方法返回promise。這樣就實現了多個非同步操作的序列操作。 

b)實現了多個不同非同步庫之間的轉換。

var p1 = new promise(function (resolve, reject) )

var p2 = new promise(function (resolve, reject) )

p2.then(result => console.log(result))

p2.catch(error => console.log(error))

// error: fail

promise.all方法用於將多個promise例項,包裝成乙個新的promise例項。是我們專案中正在使用的方式。如var p = promise.all([p1,p2,p3]);p的狀態由p1、p2、p3決定,分成兩種情況。
(1)只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成乙個陣列,傳遞給p的**函式。

(2)只要p1、p2、p3之中有乙個被rejected,p的狀態就變成rejected,此時第乙個被reject的例項的返回值,會傳遞給p的**函式。

四.generator

generator最大的特點就是可以實現函式的暫停、重啟,這個特性非常有利於解決非同步操作有兩個名詞需要注意yield 和 next。

generator的解決機制有點像執行緒.next方法的作用是分階段執行generator函式。每次呼叫next方法,會返回乙個物件,表示當前階段的資訊(value屬性和done屬性)。value屬性是yield語句後面表示式的值,表示當前階段的值;done屬性是乙個布林值,表示generator函式是否執行完畢,即是否還有下乙個階段。

yield 命令是標誌非同步操作的標誌,如果去掉此命令,函式就會像執行同步函式那樣執行就暫停,等到執行權返回,再從暫停的地方繼續往後執行。 

generator 函式的還提供了資料交換和錯誤處理機制。其函式內部還可以部署錯誤處理**,捕獲函式體外丟擲的錯誤。

function* gen(x) catch (e)

return y;

}var g = gen(1);

g.next();

g.throw('出錯了');

// 出錯了

除此之外,generator函式還有兩個小幫手thunk函式(自動控制generator函式的流程,接收和交還程式的執行權的一種機制)和co模組(用於generator函式的自動執行。)

五.async await

es7提供了async函式,成為generator函式的語法糖,它主要就是用async來說代替*,用await來代替yield,除此之外,他還帶來了一些便利之處: 

1.generator函式的呼叫需要借助next方法或者是co模組,而async和普通函式的呼叫一樣,不需要借助任何函式; 

2.co模組約定,yield命令後面只能是thunk函式或promise物件,而async函式的await命令後面,可以是promise物件和原始型別的值 

注意的是: await 命令只能用在 async 函式之中,如果用在普通函式,就會報錯。

async function dbfuc(db) , {}, {}];

// 報錯

docs.foreach(function (doc) );

}

上面**會報錯,因為 await 用在普通函式之中了。但是,如果將 foreach 方法的引數改成 async 函式,也有問題。

async function dbfuc(db) , {}, {}];

// 可能得到錯誤結果

docs.foreach(async function (doc) );

}

上面**可能不會正常工作,原因是這時三個 db.post 操作將是併發執行,也就是同時執行,而不是繼發執行。正確的寫法是採用 for 迴圈。

async function dbfuc(db) , {}, {}];

for (let doc of docs)

}

如果確實希望多個請求併發執行,可以使用 promise.all 方法。

async function dbfuc(db) , {}, {}];

let promises = docs.map((doc) => db.post(doc));

let results = await promise.all(promises);

console.log(results);

}// 或者使用下面的寫法

async function dbfuc(db) , {}, {}];

let promises = docs.map((doc) => db.post(doc));

let results = ;

for (let promise of promises)

console.log(results);

}

內容涉及的不是很深入,後續會繼續補充和修改,希望大家多多指正

Node教程 非同步API

導學 通過返回值拿結果 path.join 通過函式拿結果,fs.redfile 在node中有兩種api 同步的api還有非同步的api 同步所謂的同步就是一步一步的走 非同步當前的api不會堵塞後續的 的執行 對比不能通過返回值拿結果 這裡舉例說明 讀取檔案的操作是非同步的 fs.readfil...

Node 非同步I O機制

提到js,可能就免不了單執行緒,事件機制,非阻塞i o,非同步i o等等,這些詞語。不能說理解的有多麼深刻,想談談自己的一些看法。node底層採用chrome v8 j ascript搜尋引擎,其解析的速度快,效能穩定,提供了乙個良好的解析環境。這一節從非同步i o機制來看看node自身的特點。以下...

node中的非同步操作

promise 物件有三種狀態 成功 fulfilled 失敗 rejected 等待 pending 三種狀態只能發生兩種轉換 從pending fulfilled pending rejected 並且狀態的轉換僅能發生一次。promise.all promise例項1,promise例項2 a...