深入了解Promise
- 规范-Promises/A+ 术语
- promise 一个有then方法的对象或函数,行为符合本规范;
- thenable 一个定义了then方法的对象或函数;
- 值,value 任何Javascript的合法值;
- 异常,exception throw语句抛出的值;
- 拒绝原因,reason 一个标示promise被拒绝原因的值;
- promise状态
- pending
- fulfilled
- rejected


//解析代码如下
function resolve(promise,x){
if (x === promise) {
return reject(promise,new TypeError('cannot be the same'));
}
if(isPromise(x)){
if(x.state === 'pending'){
return x.then(()=>{
resolve(promise,x.value);
},()=>{
resolve(promise,x.value);
});
}
if(x.state === 'fulfilled'){
return fulfill(promise,x.value);
}
if(x.state === 'rejected'){
return reject(promise,x.value);
}
}else if(isObject(x) || isFunction(x)){
let then;
try {
then = x.then
} catch (error) {
return reject(promise,e);
}
if(isFunction(then)){
let isCalled = false;
try {
then.call(x,function resolvePromise(y){
if(isCalled){
return;
}
isCalled = true;
resolve(promise,y);
},function rejectPromise(r){
if(isCalled){
return;
}
isCalled = true;
reject(promise,r);
});
} catch (error) {
if(!isCalled){
return reject(promise,e);
}
}
}else{
return fulfill(promise,x);
}
}else{
return fulfill(promise,x);
}
}
//ES6 Promise是符合A+规范的
const promise1 = Promise.resolve(1);
const promise2 = promise1.then(2);
const promise3 = promise2.then(Promise.resolve(3));
const promise4 = promise3.then(console.log);
//输出结果为1
- 注意点
- then、catch返回的promise是新的promise,不是原来的promise;
- Promise对象的错误会"冒泡",直到被捕获为止,错误会被下一个catch语句捕获;
- 最佳实践
- 不要忘记catch错误捕获;
- then方法中使用return;
- 传递函数给then方法;
- 不要把promise写成嵌套;
- 题目
3秒之后亮一次红灯,再过2秒亮一次绿灯,再过1秒亮一次黄灯,用promise实现多次交替亮灯的效果 - 解析
- 多少秒后亮某个颜色的灯;
- 顺序亮一批灯;
- 循环顺序亮一批灯;
//多少秒后亮某个颜色的灯
function light(color,second){
return new Promise(function(resolve,reject){
setTimeout(() => {
console.log(color);
resolve();
}, second * 1000);
});
}
//顺序亮灯
function orderLights(list){
let promise = Promise.resolve();
list.forEach(element => {
promise = promise.then(function(){
return light(element.color,element.second);
});
});
//循环顺序亮灯
promise.then(function(){
return orderLights(list);
});
}
orderLights([{color:'red',second:3},{color:'green',second:2},{color:'yellow',second:1}]);
效果图如下:

async函数
- async函数
- 一个语法糖 使异步操作更简单
- 实现原理:Generator + 自动执行器
- 返回值 返回值是一个promise对象
- return的值是promise resolved时候的value
- throw的值是promise rejected时候的reason
- await
- 只能出现在async函数内或最外层
- 等待一个promise对象的值
- await的promise状态为rejected,后续执行中断
async function f(){
await Promise.reject('error');
console.log(1);
await 100;
}
f();
上面的代码什么都不会打印,执行到await Promise.reject('error');时候程序中断,不会再往后执行,如果想让后面的代码执行怎么写?

- async函数实现原理
async function example(params){
//
}
function example(params){
return spawn(function*(){
//
});
}
function spawn(genF){
return new Promise(function(resolve,reject){
const gen = genF();//生成器对象
function step(nextF){
let next;
try {
next = nextF();//执行gen.next
} catch (error) {
return reject(e);
}
if(next.done){
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v){
step(function(){
return gen.next(v);
})
},function(e){
step(function(){
return gen.throw(e);
})
});
}
step(function(){
return gen.next(undefined);
})
});
}
Generator函数
-
迭代器
迭代器有next方法,执行返回结果对象,结果对象是value和done -
可迭代协议
1、Symbol.iterator属性
2、内置可迭代对象 String Array Map Set等 -
迭代器协议
1、next方法,返回done和value -
ES5实现迭代器
-
生成器
- Generator函数是生成器,用来生成迭代器,是ES6异步编程解决方案
- 声明:通过function*声明
- 返回值:符合可迭代协议和迭代器协议的生成器对象,就是迭代器
- 特点:在执行时能暂停,又能从暂停处继续执行
- 生成器对象组成:next(param) return(param) throw(param)
- yield
- 只能出现在Generator函数
- 用来暂停和恢复生成器函数
- yield*生成器函数/可迭代对象
- 委托给其他可迭代对象
- 作用:复用生成器,交出控制权
- next执行
- 遇yield暂停,将紧跟yield表达式的值作为返回的对象的value
- 没有yield,一直执行到return,将return的值作为返回的对象的value
- 没有return,将undefined作为返回的对象的value
- next参数
- next方法可以带一个参数,该参数将会被当做上一个yield表达式的返回值
- return(param)
- 给定param值终结遍历器,param可缺省,即为undefined
- throw(param)
- 让生成器对象内部抛出错误
Generator函数的实现原理
协程
- 一个线程存在多个协程,但同时只能执行一个;
- Generator函数是协程在ES6的实现;
- Yield挂起协程(交给其他协程),next唤醒协程;
- Generator函数应用
- 需求:异步读取三个文件,但是要按照顺序的打印出file1 file2 file3的内容
- 如果用ayncs实现的话很简单;
上面f的耦合度太高,为了解决这个问题,用Thunk函数
- Thunk函数
- 求值策略 传值调用,传名调用sum(x+1,x+2)
- thunk函数是传名调用的实现方式之一
- 可以实现自动执行Generator函数
- co模块源码分析