Promise 对象是用来处理异步操作的工具,解决开发者对异步回调的烦恼。
极简版
class Defer{
succeed = null
fail = null
state = ‘pending‘
constructor(fn) {
fn(this.resolve.bind(this), this.reject.bind(this))
}
resolve(result) {
setTimeout(() => {
this.state = ‘fulfilled‘
this.succeed(result)
})
}
reject(reason) {
setTimeout(() => {
this.state = ‘rejected‘
this.fail(reason)
})
}
then(succeed, fail) {
this.succeed = succeed
this.fail = fail
}
}
1.Promise 参数 executor
当新建一个promise需要用户传递一个executor函数,其形参包含Promise自行传递的resolve,reject两个方法,分别表示代理的值解析成功并传递值,代理的值解析失败并传失败原因。而如果executor在执行过程中出错,则promise立即被拒绝(调用reject)。
function Defer(executor){ if(!(this instanceof Defer)){ throw ‘Async is a constructor and should be called width "new" keyword‘; } if(typeof executor !== ‘function‘){ throw ‘Async params must be a function‘; } try{ executor.call(this, this.resolve.bind(this), this.reject.bind(this));//传递resolve,reject方法 }catch(e){//报错立即拒绝 this.reject(e); } } Async.prototype = { constructor : Async, resolve : function(value){ this.value = value;//缓存代理的值 }, reject : function(reason){ this.rejectReason = reason;//缓存失败原因 } }
2.promise状态
Defer.prototype = { constructor : Async, resolve : function(value){ this.value = value;//缓存代理的值 this.status = ‘resolved‘; }, reject : function(reason){ this.rejectReason = reason;//缓存失败原因 this.status = ‘rejected‘; } }
3.then(onFulfilled,onRejected)重要部分
then返回的是新的promise对象
//then中的onfulfilled传的参数为数值,则直接返回数值,如果为函数,则直接去调用函数。
then参数调用时期和要求
(1) onFulfilled(onResolved):可选参数,如果不是函数则必须忽略;
(2) onRejected:可选参数,如果不是函数则必须忽略;
(3) 当promise成功执行,所有onFulfilled按注册顺序执行,如果promise被拒绝,所有onRejected按注册顺序执行;
(4) onFulfilled 和 onRejected必须作为纯函数调用
(5) promise的executor执行完毕并调用resolve或reject方可调用then参数onFulfilled 和 onRejected。
(6) 无论promise状态是resolved还是rejected,只要还有未执行onFulfilled,onRejected或catch(只处理reject状态)存在且调用,返回的promise均为resolved状态;(该规则在下一节”triggerThen处理”和下下节”catch异常“会有注释,一看便知)
对于规则4,必须作为传函数调用。所以传函数调用,是不包含在Object的属性当中直接引用,并且this的值是undefined。
onFulfilled.call(undefined, promise_value);
对于规则5,等待executor执行完毕并调用resolve或reject方可调用then参数。then方法就是缓存参数。
function Defer(executor) {
if (!(this instanceof Defer)) {
throw ‘Defer is a constructor and should be called width "new" keyword‘;
}
if (typeof executor !== ‘function‘) {
throw ‘Defer params must be a function‘;
}
this.thenCache = [];//{resolve:,reject:}
this.errorHandle = null;
this.status = ‘pendding‘;
this.value = null;
this.rejectReason = null;
var self = this;
setTimeout(function () {
try {
executor.call(self, self.resolve.bind(self), self.reject.bind(self));//传递resolve,reject方法
} catch (e) {
self.reject(e);
}
}, 0);
return this;
}
Defer.prototype.resolve = function (value) {
this.status = ‘resolved‘;
this.value = value;
this.triggerThen();
};
Defer.prototype.reject = function (reason) {
this.status = ‘rejected‘;
this.rejectReason = reason;
this.triggerThen();
};
Defer.prototype.then = function (resolve, reject) {
var todo = { resolve: resolve, reject: reject };
this.thenCache.push(todo);
return this;
};
Defer.prototype.triggerThen = function () {
var current = this.thenCache.shift();
var res = null;
if (!current && this.status === ‘resolved‘) {//成功解析并读取完then cache
return this;
} else if (!current && this.status === ‘rejected‘) {//解析失败并读取完then cache,直接调用errorHandle
if (this.errorHandle) {
this.value = this.errorHandle.call(undefined, this.rejectReason);
this.status = ‘resolved‘;
}
return this;
};
if (this.status === ‘resolved‘) {
res = current.resolve;
} else if (this.status === ‘rejected‘) {
res = current.reject;
}
if (typeof res === ‘function‘) {
try {
this.value = res.call(undefined, this.value || this.rejectReason);//重置promise的value
this.status = ‘resolved‘;
this.triggerThen();//继续执行then链
} catch (e) {
this.status = ‘rejected‘;//异常,则promise为reject
this.rejectReason = e;
return this.triggerThen();//触发then链
}
} else {//不是函数则忽略
this.triggerThen();
}
};
Defer.prototype.catch = function (fn) {
if (typeof fn === ‘function‘) {
this.errorHandle = fn;
}
};
(方法返回一个promise实例,所有的promise都返回resolved,则resolved。如果有一个promise失败(rejected),则实例回调失败,失败原因返回第一个promise的结果)
Promise2.all = function(arrP) {
let list = []
let len = 0
let hasErr = false
return new Promise2((resolve, reject) => {
for(let i = 0; i < arrP.length; i++) {
arrP[i].then( data=> {
list[i] = data
len++
len === arrP.length && resolve(list)
}, error => {
!hasErr && reject(error)
hasErr = true
})
}
})
}
方法返回一个promise实例,一旦迭代器中的某个 promise 完成(resolved)或失败(rejected),返回的 promise 就会 resolve 或 reject
返回第一个resolve或者reject的结果值。
Promise2.race = function(arrP) {
let hasValue = false
let hasError = false
return new Promise2((resolve, reject) => {
for(let i = 0; i < arrP.length; i++) {
arrP[i].then(data => {
!hasValue && !hasError && resolve(data)
hasValue = true
}, error => {
!hasValue && !hasError &&reject(error)
hasError = true
})
}
})
}
方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
适用于:多个彼此不依赖的异步任务完成时,可以知道每个promise的结果。
Defer.allSettled = function (values) {
function isPromise(x) {
if ((typeof x === ‘object‘ && x != null) || typeof x === ‘function‘) {
if (typeof x.then == ‘function‘) {
return true;
}
}
return false;
}
return new Defer((resolve, reject) => {
let arr = [];
let times = 0;
function collectResult(val, key, obj) {
arr[key] = obj;
if (++times === values.length) {
return resolve(arr);
}
}
// 循环每一项拿到返回结果
values.forEach((element, index) => {
if (element && isPromise(element)) {
element.then(y => {
let obj = {
status: ‘fulfilled‘,
value: y,
}
collectResult(y, index, obj)
}, (err) => {
let obj = {
status: "rejected",
reason: err
}
collectResult(err, index, obj)
})
} else {
let obj = {
status: ‘fulfilled‘,
value: value,
}
collectResult(value, index, obj)
}
});
})
}
手写promise.any()
返回第一个成功的 promise 。只要有一个 promise 成功此方法就会终止,它不会等待其他的 promise 全部完成。如果没有成功的,则将返回一个失败的promise和AggregateError类型的实例。是一个Error的子类,将用于把单一的错误集合在一起。
Defer.any = function (values) {
const num = values.length;
const rejectedList = new Array(num);
let rejectedNum = 0;
return new Defer((resolve, reject) => {
values.forEach((el, i) => {
Defer.resolve(el).then(
resolve(el)
).catch(err => {
rejectedList[index] = err;
if (++rejectedNum === num) {
reject(rejectedList);
}
})
})
})
}
手写实现 Promise.prototype.finally()
finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
实例执行完then或者catch触发,
Defer.prototype.finally=function(cb){
return new Defer((resolve,reject)=>{
this.then((result)=>{
cb();
resolve(result);
},(reason)=>{
cb();
reject(reason);
})
})
}
代码完整:https://github.com/yaqian96/promise.git
原文:https://www.cnblogs.com/lyq1996/p/14202289.html