Js中有使人頭疼的地獄回調的問題,因而有了Promise,有了鏈式調用,基於Promise也出現了各類異步解決方案就出現了,其中最好的我的感受應該是async/await的解決方案了,一直以來都是模模糊糊的使用,直到碰見了循環與異步的問題,因而花時間查閱資料從1分懂到了4分懂.javascript
網上關於Promise的文章有不少,也講得很好,這裏也簡單的記錄一下.java
Promise不只經過鏈式調用解決了回調嵌套的問題,還解決了回調函數中使用 return 和 throw 的問題,最重要的是它在異步解決方案中的使用.
Promise一共擁有pending/resloved/rejected(進行中/已完成/已失敗)這三個狀態,resloved/rejected狀態能夠由pendding狀態變化獲得,並且這個狀態一旦變化就不會再更改.數組
Promise.all()
// 多個Promise並行進行,當全部Promise reslove時reslove.當有一個Promise reject時rejectPromise.race()
// 與Promise.all相似,差異在當第一個Promise reslove時reslove.Promise.then()
// 用於鏈式調用Promise.catch()
// 捕獲rejectfunction sleep(dely) { return new Promise((reslove) => { setTimeout(() => { console.log(`dely ${dely}s`) reslove(); }, dely * 1000); }) } (async () => { console.log('before sleep') await sleep(2); console.log('after sleep') })() /** console * before sleep * dely 2s * after sleep */
這個是ES7中的異步解決方案,在Node v8.0.0及其以上已經原生支持,在低版本的Node中須要開啓--harmony-async-await
選項異步
例若有以下設定: 每一個人的碎覺時間都是固定值,若是有多我的碎覺,則後一我的的碎覺時間是前面碎覺時間的累積和,寫一個函數在傳入name數組時能實現以上描述,話很少說上代碼async
const users = { // 定義3我的,且每一個人睡覺時間是1 leo: { name: 'leo', sleep: 1 }, mick: { name: 'mick', sleep: 1 }, jack: { name: 'jack', sleep: 1 } } function sleep(name, sleep) { // 碎覺函數,包括打印當前碎覺時間,和累加未碎覺人的時間 return new Promise((reslove) => { setTimeout(() => { console.log(`${name} sleep ${sleep}`); Object.keys(users).forEach(u => { if (name !== u) { users[u].sleep += sleep; } }) reslove(); }, sleep * 1000); }) }
我第一次寫出來是這樣的函數
(function consoleSleep(names) { return Promise.all(names.map(async n => { await sleep(users[n].name, users[n].sleep) })) }(['leo', 'mick', 'jack'])) /** console * leo sleep 1 * mick sleep 1 * jack sleep 1 */
當場我就很懵逼,把name 數組拿來循環,而後循環中等待當前sleep時的各類異步操做,但結果讓人很憂桑,在分析問題後,發現這是一個串行執行異步操做的問題,
好吧,Promise.all()
是並行進行的,但是在去掉Promise.all後結果任然沒有改變,通過各類查資料後發現是map的問題(笑哭)(map和forEach都是並行迭代的),好吧再改代碼學習
(async function consoleSleep(names) { for(let i = 0; i < names.length; i++) { await sleep(users[names[i]].name, users[names[i]].sleep) } }(['leo', 'mick', 'jack'])) /** console * leo sleep 1 * mick sleep 2 * jack sleep 4 */
終於實現了功能,大功告成code
Promise不只解決了回調嵌套還提供了異步解決的方式,可使用Promise封裝異步操做而後使用async/await來把異步操做變成同步的,在循環中使用Promise時要注意並行和串行兩種方式帶來的不一樣操做結果,固然其它庫也提供了相應封裝的方法(例如bluebird有mapSeries能夠直接迭代串行執行多個Promise).
ps: 學習了,map/forEach是並行的迭代,而不是同步的循環,切記!切記!切記!對象