javascript異步編程(一)-現狀

寫在前面, 這個話題其實還挺大的, 我本身恐怕力有不逮, 因此只能算是筆記總結, 寫的確定會有點簡略. 有錯誤實在太正常了. 但願能多多指教.python

這篇文章僅僅是解釋一下現有的異步編程方案不涉及具體原理, 可是個人想法是試試看能不能每一個方案都本身實現一遍, 因此多是系列文章也可能就此太監了.web

回調函數

image

想必你們都看過上面的圖片, 雖然不是js代碼, 甚至不是回調, 可是各位同窗估計對callback hell感同身受. 可是事實上回調函數跟異步編程並無必然的聯繫. 回調只是一種設計模式. 同步代碼一樣能夠使用回調只是大部分時候會讓人以爲畫蛇添足而已.ajax

你們都知道回調並非那麼優雅, 不少時候代碼可能寫成這樣:編程

asyncJob1(function () {
  asyncJob2(function () {
    asyncJob3(function () {
      // your code
    })
  })
})
複製代碼

雖然問題算是解決了吧, 可是代碼看着真是使人頭痛. 玩意邏輯稍微複雜一點說不定真會出現下面的狀況: c#

image

大概美軍也是回調寫多了吧2333.設計模式

事件驅動

大部分gui程序都是採用事件驅動, web固然也不例外, 最典型的就是dom事件:promise

div.on('click', function () {
  // balabala
})
複製代碼

這個幾乎都是跟回調和事件循環相關的, 後面會詳細講到的.dom

Promise

根據promise/A+的規範:koa

一個Promise必須處在其中之一的狀態:pending, fulfilled 或 rejected. 若是是pending狀態,則promise能夠轉換到fulfilled或rejected狀態。 若是是fulfilled狀態,則promise不能轉換成任何其它狀態。 若是是rejected狀態,則promise不能轉換成任何其它狀態。異步

Promise都會有個then方法, 制定了fulfilled和rejected兩種請況的回調, 同時then會返回一個Promise對象, 這就容許咱們鏈式調用了:

ajax('xxx').then(res => res).then(res => res)
複製代碼

雖然Promise的方案比回調已經好太多了. 可是不難發現多個then其實未必比回調好看太多, 只能說把回調鋪平了. 可能Promise並非最優雅的解決方案.

generator

generator在各個語言裏都有出現, python,c#等, 這裏不說概念, 只說在js裏該怎麼使用就行, 基本理解就是generator是擁有多個返回值的函數, 每次調用next就會調用一次返回. 這就是所謂 控制權移交, 固然這樣不足以體現其優越性, generator最重要的特性就是分步數據傳遞: next的參數能夠做爲上次yield的返回值, 其實直覺上不是很能理解, 不過咱們這裏只要知道有這麼個東西就成, 下面是代碼示例:

var f = function* (x) {
	var y = yield x + 1
	yield y + 1
	return y
}


var t = f(1)

var s = t.next()
console.log(s) // 2
var p = t.next(4) // 這裏的4做爲上次yield的返回值
console.log(p) // 5
複製代碼

有這麼一個特性, 那麼下面的操做性就很強了, 好比tj的著名的co:

co(function* () {
  var result = yield Promise.resolve(true);
  return result;
}).then(function (value) {
  console.log(value);
}, function (err) {
  console.error(err.stack);
});
複製代碼

能夠說寫法已經很同步了. 固然這個也不是最終的解決方案, 否則爲何koa2要用async/await呢hhh

async/await

一樣對於async/await 咱們先不糾結其原理, 咱們只須要知道它是generator和promise兩者結合起來的語法糖(不過也真夠甜的)

每一個async必然返回一個Promise對象, 因此async會像瘟疫一個把你的每一個函數都變成async函數, 所謂能夠async的終將async, 下面是例子:

// Promise的解決方案
function foo () {
  return ajax('xxx').then(res => res).then(res => res)
}


async function bar () {
  try {
    const response = await ajax('xxx')
    console.log(response)
  } catch (e) {
    throw e
  }
}
複製代碼

是否是優雅了太多, 除了一大片async/await, 不過也算小小的代價.

利用午休時間碼了出來, 不知道有多少錯誤呢hhh

image
相關文章
相關標籤/搜索