发展历程:
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