發展歷程:
callback -> pub-sub -> promise -> generator -> async + awaitjavascript
ajax(url, () => { // 處理邏輯 ajax(url1, () => { // 處理邏輯 ajax(url2, () => { // 處理邏輯 }); }); });
回調地獄,代碼難以維護vue
export default class PubSub { constructor() { // events裏存放的是全部的具名事件 this.events = {}; } // 提供訂閱功能 subscribe(event, callback) { let self = this; if (!self.events.hasOwnProperty(event)) { self.events[event] = []; } // 沒有作去重 return self.events[event].push(callback); } // 提供發佈功能 publish(event, data) { let self = this; if (!self.events.hasOwnProperty(event)) { return []; } return self.events[event].map(callback => callback(data)); } }
參考另外一個工程:
pub-subjava
Pending----Promise對象實例建立時候的初始狀態 Fulfilled----能夠理解爲成功的狀態 Rejected----能夠理解爲失敗的狀態
Promise.resolve(1) //每次調用返回的都是一個新的Promise實例(這就是then可用鏈式調用的緣由) .then(x => x + 1) .then(x => { throw new Error("My Error"); //若是then中出現異常,會走下一個then的失敗回調 }) .catch(() => 1) //return -> 包裝成 Promise.resolve(1) .then(x => x + 1) .then() //參數穿透 .then(x => console.log(x)) //2 .catch(console.error); //catch 會捕獲到沒有捕獲的異常
手寫 Promisenode
缺點:react
迭代器git
Generator 能夠中斷函數的執行,這就爲咱們用同步方式寫異步提供了可能github
function* foo(x) { let y = 2 * (yield x + 1); //yield可暫停,next方法可啓動,每次返回的是yield後的表達式結果 let z = yield y / 3; //yield表達式自己沒有返回值,或者說老是返回undefined。next方法能夠帶一個參數,該參數就會被看成上一個yield表達式的返回值 return x + y + z; } let it = foo(5); console.log(it.next()); // => {value: 6, done: false} console.log(it.next(12)); // => {value: 8, done: false} console.log(it.next(13)); // => {value: 42, done: true}
var fetch = require("node-fetch"); function* gen() { var r1 = yield fetch("https://api.github.com/users/github"); var r2 = yield fetch("https://api.github.com/users/github/followers"); var r3 = yield fetch("https://api.github.com/users/github/repos"); console.log([json1.bio, json2[0].login, json3[0].full_name].join("\n")); }
對於上面三個請求咱們能夠這樣寫ajax
var g = gen(); var result1 = g.next(); result1.value .then(function(data) { return data.json(); }) .then(function(data) { return g.next(data).value; }) .then(function(data) { return data.json(); }) .then(function(data) { return g.next(data).value; }) .then(function(data) { return data.json(); }) .then(function(data) { g.next(data); });
更好的辦法是使用遞歸json
function run(gen) { var g = gen(); function next(data) { var result = g.next(data); result.value .then(function(data) { return data.json(); }) .then(function(data) { next(data); }); } next(); } run(gen);
co這個庫所作的事情
co(gen)即自執行 generatorapi
參考文獻 Generators
自帶 generator 執行器
async //返回一個Promise await //後面跟一個Promise
function fetch() { return fetchData() .then(value1 => { return fetchMoreData(value1); }) .then(value2 => { return fetchMoreData2(value2); }); } async function fetch() { const value1 = await fetchData(); const value2 = await fetchMoreData(value1); return fetchMoreData2(value2); }
const fetchData = data => new Promise(resolve => setTimeout(resolve, 1000, data + 1)); const fetchValue = async function() { var value1 = await fetchData(1); var value2 = await fetchData(value1); var value3 = await fetchData(value2); console.log(value3); }; fetchValue();
實際應用:
「異步的」 setState 如何同步獲取 state
這篇文章有詳細的說明
setStateAsync(state){ return new Promise (resolve =>{ this.setState(state,resolve) }) }
babel編譯的結果
測試題 2
async function test1() { await new Promise(resolve => { setTimeout(() => resolve(), 0); }).then(() => console.log(1)); setTimeout(() => console.log(2), 0); new Promise(resolve => { console.log(3); resolve(); }).then(() => { console.log(4); }); console.log(5); } test1().then(() => { console.log(7); }); console.log(6); // 6135472