我了解到的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...