JavaScript中異步函數

JavaScript 中常見的異步函數有:定時器,事件和ajax等,那麼如何來處理這些異步函數呢,常用的方法有下面幾種:

1. 回調函數

function eat() {
  console.log('好的,我開動咯');
}

function cooking(cb) {
  console.log('媽媽認真做飯');
  setTimeout(function () {
    console.log('小明快過來,開飯啦')
    cb();
  }, 1000);
}

function read() {
  console.log('小明假裝正在讀書');
}

cooking(eat);
read();

/* 執行順序:
媽媽認真做飯
小明假裝正在讀書
小明快過來,開飯啦
好的,我開動咯
*/

優點: 簡單
缺點: 如果有大量異步並存在依賴會形成回調地獄

2. 事件

function eat() {
  console.log('媽媽敲門啦,該去吃飯啦');
}

function cooking() {
  console.log('媽媽認真做飯');
  setTimeout(function () {
    console.log('小明,出來吃飯啦')
    bus.$emit('done');
  }, 3000);
}

function read() {
  console.log('小明又假裝正在讀書');
  bus.$on('done', eat);
}

cooking();
read();
/* 執行順序:
媽媽認真做飯
小明又假裝正在讀書
小明,出來吃飯啦
媽媽敲門啦,該去吃飯啦
*/

優點:代碼解耦
缺點:處理回調地獄需要定義和監聽大量的事件

3. 發佈訂閱

function eat() {
  console.log('爸爸叫我去吃飯啦');
}

function cooking() {
  console.log('媽媽認真做飯');
  setTimeout(function () {
    console.log('孩子他爸,叫小明出來吃飯');
    Dad.publish("done");
  }, 3000);
}

function read() {
  console.log('小明依舊假裝正在讀書');
  Dad.subscribe('done', eat);
}

cooking();
read();

/* 執行順序:
媽媽認真做飯
小明依舊假裝正在讀書
孩子他爸,叫小明出來吃飯
爸爸叫我去吃飯啦
*/

優點:創建了一下中介者(Dad)來管理髮布和訂閱,事件越多越強大
缺點:仍然需要定義一大堆事件

4. promise

function read() {
  console.log('小明認真讀書');
}

function eat() {
  return new Promise((resolve, reject) => {
    console.log('好嘞,吃飯咯');
    setTimeout(() => {
      resolve('飯吃飽啦');
    }, 1000)
  })
}

function wash() {
  return new Promise((resolve, reject) => {
    console.log('唉,又要洗碗');
    setTimeout(() => {
      resolve('碗洗完啦');
    }, 1000)
  })
}

function mop() {
  return new Promise((resolve, reject) => {
    console.log('唉,還要拖地');
    setTimeout(() => {
      resolve('地拖完啦');
    }, 1000)
  })
}

const cooking = new Promise((resolve, reject) => {
  console.log('媽媽認真做飯');
  setTimeout(() => {
    resolve('小明快過來,開飯啦');
  }, 3000);
})

cooking.then(msg => {
  console.log(msg);
  return eat();
}).then(msg => {
  console.log(msg);
  return wash();
}).then(msg => {
  console.log(msg);
  return mop();
}).then(msg => {
  console.log(msg);
  console.log('終於結束啦,出去玩咯')
})
read();

/* 執行順序:
媽媽認真做飯
小明認真讀書
小明快過來,開飯啦
好嘞,吃飯咯
飯吃飽啦
唉,又要洗碗
碗洗完啦
唉,還要拖地
地拖完啦
終於結束啦,出去玩咯
*/ 

優點: 既有回調函數的簡單直觀,又具備事件的狀態內聚
缺點: 錯誤會被吃掉,無法通過window.onerror捕獲

參考:
https://github.com/frontend9/fe9-library/issues/14
https://github.com/mqyqingfeng/Blog/issues/98

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章