上一篇写到了resolvePromise这个方法,这个方法是根据返回不同的x值来进行不同的逻辑处理的。
基本使用
let p = new Promise(function(resplve,reject){
resolve()
})
let p2 = p.then(function(){
// return p2
// return 100
// return new Promise(functionl(resolve,reject){
resolve(200)
})
})
Promise.all([promise1,promise2,100]).then(function(data){
console.log(data);
})
resolvePromise实现代码
function resolvePromise(promise2,x,resolve,reject){
// 加入返回的x和promise2相等,这样promise2会等待x执行成功或者失败然后才会调用。这样形成了一个自身引用。抛出异常
if(x===promise2){
throw new TypeError('TypeError: Chaining cycle detected for promise #<Promise>')
}
let called; // 规范要求 一旦成功了 就不能再调用失败
// x是一个对象或者函数 说明x可能是一个promise
if(x!=null && type x ==='object' || typeof x === 'function'){
try{ // 因为当取x.then 的时候可能会抛出异常,所以try捕获一下
let then = x.then
if(typeof then ==='function'){
// 为什么不直接x.then执行呢? 因为x.then 的时候 不一定哪一次执行的时候会抛出错误
then.call(x,function(y){
// 因为x执行成功的时候,返回的y可能是原始值、promise、异常,所以这里需要在递归调用一下
if(!called){called = true}else{return}
resolvePromise(promise2,y,resolve,reject)
},function(r){
// 错误直接reject
if(!called){called = true}else{return}
reject(r)
})
}else{ // x为普通值
resolve(x)
}
}catch(e){
if(!called){called = true}else{return}
reject(e)
}
}else{
resolve(x)
}
}
Promise.catch
catch方法实际就是then方法成功的回调传递的是null
Promise.prototype.catch = function(onRejected){
return this.then(null,onRejected)
}
Promise.resolve
Promise.resolve = function(value){
return new Promise(function(resolve,reject){
resolve(value)
})
}
Promise.reject
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason)
})
}
Promise.all
Promise.all = function(promises){
return new Promise(function(resolve,reject){
let arr = [];
let i = 0;
function processData(index,data){
arr[index] = data;
// 这里为什么用一个记数的i,而不是直接用arr.length ===promises.length 判断呢?
// 因为当执行all方法的时候,如上所述数组里面的100先执行 这时候索引为2 arr的length 已经为3了 直接满足条件判断,而此时其余的promise还没有执行完成。所以需要一个计数器来进行判断
if(++i === promises.length){
resolve(arr)
}
}
for(let i = 0;i<promises.length;i++){
let promise = promises[i];
if(typeof promise.then === 'function'){
// 当前项为promise
promise.then(function(data){
processData(i,data);
},reject)
}else{
// 非promise 为原始值
processData(i,promise)
}
}
})
}
Promise.race
Promise.race = function(promises){
return new Promise(function(resolve,reject){
for(let i = 0;i<promises.length;i++){
let promise = promises[i];
if(typeof promise.then === 'function'){
promise.then(resolve,reject)
}else{
resolve(promise)
}
}
})
}
Promise.finally(无论成功还是失败finally里面的方法都会执行)
Promise.prototype.finally = function(cb){
return this.then(function(data){
cb();
return data
},function(err){
cb();
throw err;
})
}
Promise.deferred(相当于promise的语法糖,方便书写)
Promise.deferred = Promise.defer = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
// 如下使用
let fs = require('fs')
function read(url){
let defer = Promise.defer();
fs.readFile('./1.txt','utf8',function(err,data){
if(err) defer.reject(err)
defer.resolve(data)
})
return defer.promise;
}
Promise的值穿透(就是then可以不传递参数,交到下一个then来处理)
Promise.prototype.then = function(onFulfilled,onRejected){
// 处理不传递成功 添加默认值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(data){return data}
// 处理不传递失败 添加默认值
onRejected = typeof onRejected ==='function' ? onRejected : function(err){ throw err}
//.....
}
Promise测试
可以使用npm库promises-aplus-tests 来进行测试