ES6: Promise

一、概述

ES2015 Promise函数是对PromiseA+规范的完成,而且严格遵守该规范。

二、APIs

2.1 建立Promise对象

Promise组织函数的参数是个包括两个参数的函数,而且该函数的参数离别对应resolve, reject操纵(resolve,reject也是函数)。而且只能经由历程这两个参数转变Promise的状况。

function asynOperation(){
    var promise = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject(1,2,3); // 挪用reject操纵,并通报reason参数。虽然通报多个参数,但只把第一个作为reson值,相符Promise A+规范
        }, 3000)
    });
    return promise;
    
}
asynOperation().then(function(value){
    console.log('ES2015 Promise: resolved and value is ' + value);
}, function(reason){
    console.log('ES2015 Promise: rejected and reason is ' + reason);
})

上面的代码用zpotojs完成:

/*
    ZeptoJS Deferred
*/
function AsynOperation1(){
    var deferred = $.Deferred();
    setTimeout(function(){
        deferred.reject(1, 2, 3);
    }, 3000);
    return deferred.promise();
}
AsynOperation1().then(function(val){
    console.log('Fullfilled: ' + val);
}, function(reason){
    console.log('Rejected: ' + reason);
})

2.2 Promise.prototype.catch

catch要领用来增加Rejected状况回调,是then要领的一种子集。

asynOperation().catch(function(reason){
})
// 等价于
asynOperation().then(undefined, function(reason){
})

2.3 Promise.reject(reason)

Promise组织函数的静态要领,建立个Promise对象并以reason值挪用reject句柄函数。换句话说该静态函数返回个处于“Rejected”状况的Promise对象。

var p = Promise.reject(1);
// 等价于
var p = new Promise(function(resolve, reject){
  reject(1);
})

2.4 Promise.resolve(value)

Promise组织函数的静态函数,建立一个Promise对象并以value值作为参数挪用resolve句柄函数。换句话说该静态函数返回个处于“fullfilled”状况的Promise对象。

var p = Promise.resolve(1);
// 等价于
var = new Promise(function(resolve){
  resolve(1);
})

2.5 Promise.all(iterable)

2.5.1 引见

Promise组织函数的静态函数,参数是Promise对象组成的可迭代数据鸠合。建立个Promise对象,而且参数指定的所以Promise都处理后,该Promise对象该被处理,反之假如个中存在rejected的Promise,则该Promise对象被rejected。
定义个异步操纵:

function asynOperation(value, reason){
    var promise = new Promise(function(resolve, reject){
        setTimeout(function(){
            value === undefined ? reject(reason) : resolve(value);
        }, 3000)
    });
    return promise;
    
}

var p1 = asynOperation(1),
    p2 = asynOperation(2),
    p3 = asynOperation(3);
Promise.all([p1, p2, p3]).then(function(value){
    console.log('all resolved: value is ' + value); // value是[1, 2, 3] 
})

假如参数元素中发作rejected操纵,则立马reject返回的Promise:

var p1 = asynOperation(1),
    p2 = asynOperation(undefined, 2), // reject操纵
    p3 = asynOperation(undefined, 3); // reject操纵
p2.catch(function(reson){
    console.log('p2')
})
p3.catch(function(reson){
    console.log('p3')
})
Promise.all([p1, p2, p3]).then(function(value){
    console.log('all resolved: value is ' + value)
}, function(reason){
    console.log('one rejected: reason is ' + reason); // reson值即是发作reject操纵的promise对象的reason,即p2
})

显现效果:

《ES6: Promise》

2.5.2 对照$.when

Promise.all和$.when很相似。主题功用差不多,参数通报体式格局不一样:ES2015中把一切的Promise对象的value构建个数组,而$.when是离别通报的。

function AsynOperation1(value, reason){
    var deferred = $.Deferred();
    setTimeout(function(){
        value === undefined ? deferred.reject(reason) : deferred.resolve(value);
    }, 3000);
    return deferred.promise();
}
var p1 = AsynOperation1(1),
    p2 = AsynOperation1(2),
    p3 = AsynOperation1(3);
$.when(p1, p2, p3).then(function(value){
    console.log('resolved ' + value); // 注意Value的值
}, function(reason){
    console.log('rejected ' + reason);
})

2.6 Promise.race(iterable)

Promise组织函数的静态函数,参数是Promise对象组成的可迭代对象,建立个Promise对象。当参数恣意Promise对象fullfilled(rejected)时,则立马fullfill(reject)该Promise对象。

var p1 = asynOperation(1),
    p2 = asynOperation(undefined, 2),
    p3 = asynOperation(undefined, 3);
Promise.race([p1, p2, p3]).then(function(value){
    console.log('one resolved: value is ' + value); // Value=1
}, function(reason){
    console.log('one rejected: reason is ' + reason)
})

三、micro-task

Promise的回调经由历程micor-task完成的。

console.log(1)
setTimeout(function(){ console.log(2)}, 0)
Promise.resolve().then(function(){console.log(3)})
console.log(4)
// 输出应该是:1 4 3 2

四、对照Promise A+ 规范

大部分Promise A+规范的完成对”Promise处理历程”规范的完成略有不同,比方zeptoJs Deferred就没斟酌thenable状况。然则ES2015 Promise函数完整严格遵守Promise A+规范,包括对“Promise 处理历程的完成。下面举例说明完成Promise处理历程(The Promise Resolution Procedure):[[Resolve]](promise, x)

3.3.1 假如promise对象和x相称,则用TypeError对象作为reason 谢绝promise对象

var p1 = asynOperation(1);
var p2 = p1.then(function(value){
        console.log('resolved: ' + value);
        return p2; // 返回p2对象,
    },function(reason){
        console.log('rejected: ' + reason);
        }};
    });
p2.then(function(value){
    console.log('resolved: ' + value);
},function(reason){
    console.log('rejected: ' + reason);

《ES6: Promise》

var p1 = asynOperation(1);
var p2 = p1.then(function(value){
        console.log('resolved: ' + value);
         return asynOperation(2); // 返回个Promise对象,以该Prmoise对象状况决议p2的状况
    },function(reason){
        console.log('rejected: ' + reason);
    });
p2.then(function(value){
    console.log('resolved: ' + value);
},function(reason){
    console.log('rejected: ' + reason);
})

《ES6: Promise》

3.3.3 假如x是thenable,promise状况的转变取决于x.then要领的实行中resolve,reject句柄的挪用状况。并不受x.then返回值的影响。

  • A:then要领没有挪用resolve或许reject,而且没有返回值,则不会转变promose的状况
var p1 = asynOperation(1);
var p2 = p1.then(function(value){
        console.log('resolved: ' + value);
        return {name: 'john', then: function(resolve, reject){ // 返回值是个thenable对象,然则then要领没有挪用resolve或许reject,而且没有返回值
            
        }};
    },function(reason){
        console.log('rejected: ' + reason);
        
    });
p2.then(function(value){
    console.log('resolved: ' + value);
},function(reason){
    console.log('rejected: ' + reason);
})

《ES6: Promise》

  • B:then要领中挪用resolve句柄,用新value y递归挪用Promise处理历程:[[Resolve]](promise, y)
var p1 = asynOperation(1);
var p2 = p1.then(function(value){
        console.log('resolved: ' + value);
        return {name: 'john', then: function(resolve, reject){
            resolve(2); // then要领中挪用resolve句柄,用新value递归挪用Promise处理历程
        }};
    },function(reason){
        console.log('rejected: ' + reason);
    });
p2.then(function(value){
    console.log('resolved: ' + value);
},function(reason){
    console.log('rejected: ' + reason);
})
  • C:then要领中挪用reject句柄,则用雷同的reason谢绝promise.
var p1 = asynOperation(1);
var p2 = p1.then(function(value){
        console.log('resolved: ' + value);
        return {name: 'john', then: function(resolve, reject){
            reject(2); // 挪用reject句柄
        }};
    },function(reason){
        console.log('rejected: ' + reason);
    });
p2.then(function(value){
    console.log('resolved: ' + value);
},function(reason){
    console.log('rejected: ' + reason);
})
  • D:then要领中屡次挪用resolve, reject句柄,只要第一个挪用有用,其他的疏忽
  • E:then要领中抛非常,假如抛非常之前已挪用resolve或许reject句柄,则疏忽该非常,反之则以该非常为reason谢绝promise

2.3.4 其他状况,则用x作为value完成promise。

var p1 = asynOperation(undefined, 1); // 谢绝的promise
var p2 = p1.then(function(value){
        console.log('resolved: ' + value);
        return {name: 'john'};
    },function(reason){
        console.log('rejected: ' + reason);
        return 2;
    });
p2.then(function(value){
    console.log('resolved: ' + value);
},function(reason){
    console.log('rejected: ' + reason);
})

还没完毕

一道关于Promise运用的面试题

参考

  1. 是时刻运用promise了
  2. avaScript Promise迷你书(中文版)
  3. MDN
    原文作者:普拉斯
    原文地址: https://segmentfault.com/a/1190000013646453
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞