目录
前言
在学习过程中建议配合参考MDN promise和Promise/A+规范(中文翻译)、Promise/A+规范(中文翻译),可以使用MDN中案例或者promises-aplus-tests来测试。
我会在最底下放promises-aplus-tests的测试方法和完整代码。
实现Promise
构造函数
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class Promise {
constructor(executor) {
//状态
this.status = PENDING;
//成功值
this.value = undefined;
//失败值
this.reason = undefined;
//then回调数组
this.onResolveCallBacks = []
this.onRejectCallBacks = []
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
//执行then resolve回调方法
this.onResolveCallBacks.forEach(fn => fn())
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
//执行then reject回调方法
this.onRejectCallBacks.forEach(fn => fn())
}
};
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then方法
then() 方法返回一个 Promise 。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。返回Promise可以进行链式调用。
then方法是最重要也是最难的地方,弄懂了其他都简单了。
then(onFulfilled, onRejected) {
//如果没有回调函数则将上个resolve/reject结果返回给下一个
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
//返回promise对象
let promise2 = new Promise((resolve, reject) => {
const resolveMicrotask = () => {
queueMicrotask(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
const rejectMicrotask = () => {
queueMicrotask(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.status === FULFILLED) {
//异步(微任务)调用回调函数
resolveMicrotask();
return;
}
if (this.status === REJECTED) {
rejectMicrotask();
return;
}
if (this.status === PENDING) {
this.onResolveCallBacks.push(resolveMicrotask);
this.onRejectCallBacks.push(rejectMicrotask);
return;
}
});
return promise2;
}
/**
* Promise解决程序
*/
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
reject(new TypeError("Chaining cycle detected for promise #<Promise>"));
}
//x是函数或者对象
else if ((typeof x === "object" && x != null) || typeof x === "function") {
//x.then取出或者调用抛出异常返回错误
let called = false; // 标记 resolve或reject只执行一次,优先采用首次调用
try {
let then = x.then;
//如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态
if (typeof then === "function") {
then.call(x,
(y) => {
if (called) return;
called = true;
//thenable 的y可能会返回promise 所有再进一步处理
return resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
}
//then不是函数返回x
else {
resolve(x);
}
} catch (error) {
//若promise已解决或拒绝则忽略异常
if (called) return;
reject(error);
}
}
//x不是函数或者对象
else {
resolve(x);
}
};
Promise.prototype.catch()方法
catch() 方法返回一个Promise ,并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected) 相同。
//等于只有onRejected的then
catch (onRejected) {
return this.then(null, onRejected)
}
Promise.prototype.finally()方法
- finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
- finally的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。
- finally的回调函数如果返回一个resultPromise,那么Promise的结果根据resultPromise的执行结果来决定,否则回上一个Promise的执行结果
finally(callback) {
//如果回调函数返回promise,则返回此promise的resolve/reject结果
//如果回调函数不返回promise,则返回上一个promise的resolve/reject结果
return this.then(value => {
return Promise.resolve(callback()).then(()=>value)
}, reason => {
return Promise.reject(callback()).then(()=>reason)
})
}
resolve()方法
Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。
- 如果这个值是一个 promise ,那么将返回这个 promise
- 如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态
- 否则返回的promise将以此值完成。
resolve(value) {
//如果这个值是一个 promise ,那么将返回这个 promise
if (value instanceof Promise) {
return value
//如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
} else if (value && value.then && typeof value.then === 'function') {
let p = new Promise((resolve, reject) => {
resolve()
})
p.then = value.then
return p
} else {
return new Promise((resolve, reject) => {
resolve(value)
})
}
}
reject()方法
Promise.reject()方法返回一个带有拒绝原因的Promise对象。
reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
all()方法
Promise.all() 方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,并且只返回一个Promise实例, 那个输入的所有promise的resolve回调的结果是一个数组。
- 如果传入的参数是一个空的可迭代对象,则会同步地返回一个已完成(already resolved)状态的 Promise。
- 如果传入的参数不包含任何 promise,则返回一个异步完成(asynchronously resolved) Promise。
- 其它情况下返回一个处理中(pending)的Promise。这个返回的 promise 之后会在所有的 promise 都完成或有一个 promise 失败时异步地变为完成或失败。返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。
all(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== 'function') {
throw (new TypeError(`${array} is not iterable`))
}
let resultArr = []
let flag = 0
return new Promise((resolve, reject) => {
//空迭代时同步返回完成状态的Promise
if (array.length === 0) {
resolve(array)
return
}
const processResultByKey = (value, index) => {
resultArr[index] = value
flag++
//所有处理完返回成功结果
if (flag === array.length) {
resolve(resultArr)
}
}
//遍历执行
for (let i = 0; i < array.length; i++) {
let item = array[i]
if (item instanceof Promise) {
item.then(r => {
processResultByKey(r, i)
}, e => {
//如果有任何一个promise返回reject,则 all直接返回reject
reject(e)
})
} else {
//如果不是promise 则异步返回
queueMicrotask(() => {
processResultByKey(item, i)
});
}
}
})
}
allSettled()方法
Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
allSettled(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== 'function') {
throw (new TypeError(`${array} is not iterable`))
}
let resultArr = []
let flag = 0
return new Promise((resolve, reject) => {
if (array.length === 0) {
resolve(array)
return
}
const processResultByKey = (item, index, type) => {
//结果返回对象数组
if (type === 1) {
resultArr[index] = {
status: item.status,
value: item.value
}
} else {
resultArr[index] = {
status: item.status,
reason: item.reason
}
}
flag++
if (flag === array.length) {
resolve(resultArr)
}
}
for (let i = 0; i < array.length; i++) {
let item = array[i]
if (item instanceof Promise) {
item.then(() => {
processResultByKey(item, i, 1)
}, () => {
processResultByKey(item, i, 2)
})
} else {
let p = Promise.resolve(item)
p.then(() => {
processResultByKey(p, i, 1)
})
}
}
})
}
测试代码
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
Promise.allSettled(promises).then((results) => {
console.log(results);
});
any()方法
Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。
- 如果传入的参数是一个空的可迭代对象, 这个方法将会同步返回一个已经完成的 promise。
- 如果传入的任何一个 promise 已成功, 或者传入的参数不包括任何 promise, 那么 Promise.any 返回一个异步成功的 promise。
- 如果所有传入的 promises 都失败, Promise.any 将返回异步失败,和一个 AggregateError 对象,它继承自 Error,有一个 error 属性,属性值是由所有失败值填充的数组。
any(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== 'function') {
throw (new TypeError(`${array} is not iterable`))
}
let resultArr = []
let flag = 0
return new Promise((resolve, reject) => {
if (array.length === 0) {
reject(array)
return
}
const processResultByKey = (value, index) => {
resultArr[index] = value
flag++
if (flag === array.length) {
reject(new AggregateError(resultArr,'All promises were rejected'))
}
}
for (let i = 0; i < array.length; i++) {
let item = array[i]
if (item instanceof Promise) {
item.then(r => {
//如果有任何一个promise返回resolve,则all直接返回resolve
resolve(r)
}, e => {
processResultByKey(e, i)
})
} else {
//如果不是promise 则异步返回
queueMicrotask(() => {
processResultByKey(item, i)
});
}
}
})
}
race()方法
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
- 它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
- 如果传的迭代是空的,则返回的 promise 将永远等待。
- 如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 race 将解析为迭代中找到的第一个值。
race(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== 'function') {
throw (new TypeError(`${array} is not iterable`))
}
return new Promise((resolve, reject) => {
if (array.length === 0) {
return
}
for (let i = 0; i < array.length; i++) {
let item = array[i]
if (item instanceof Promise) {
item.then(r => {
resolve(r)
}, e => {
//如果有任何一个promise返回reject,则all直接返回reject
reject(e)
})
} else {
//如果不是promise 则异步返回
queueMicrotask(() => {
resolve(r)
});
}
}
})
}
}
测试
使用promises-aplus-tests库进行测试
1.安装
yarn add promises-aplus-tests
2.在package.json中加入脚本
"scripts": {
"testPromise": "promises-aplus-tests /promise.js"
},
3.在promise.js中插入以下代码
Promise.defer = Promise.deferred = function() {
let deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
};
module.exports = Promise;
4.结果
通过全部测试
完整代码
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class Promise {
constructor(executor) {
//状态
this.status = PENDING;
//成功值
this.value = undefined;
//失败值
this.reason = undefined;
//then回调数组
this.onResolveCallBacks = [];
this.onRejectCallBacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
//执行then resolve回调方法
this.onResolveCallBacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
//执行then reject回调方法
this.onRejectCallBacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
//如果没有回调函数则将上个resolve/reject结果返回给下一个
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
//返回promise对象
let promise2 = new Promise((resolve, reject) => {
const resolveMicrotask = () => {
queueMicrotask(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
const rejectMicrotask = () => {
queueMicrotask(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.status === FULFILLED) {
//异步(微任务)调用回调函数
resolveMicrotask();
return;
}
if (this.status === REJECTED) {
rejectMicrotask();
return;
}
if (this.status === PENDING) {
this.onResolveCallBacks.push(resolveMicrotask);
this.onRejectCallBacks.push(rejectMicrotask);
return;
}
});
return promise2;
}
//等于只有onRejected的then
catch(onRejected) {
return this.then(null, onRejected);
}
finally(callback) {
//如果回调函数返回promise,则返回此promise的resolve/reject结果
//如果回调函数不返回promise,则返回上一个promise的resolve/reject结果
return this.then(
(value) => {
return Promise.resolve(callback()).then(() => value);
},
(reason) => {
return Promise.reject(callback()).then(() => reason);
}
);
}
static resolve(value) {
//如果这个值是一个 promise ,那么将返回这个 promise
if (value instanceof Promise) {
return value;
//如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
} else if (value && value.then && typeof value.then === "function") {
let p = new Promise((resolve) => {
resolve();
});
p.then = value.then;
return p;
} else {
return new Promise((resolve) => {
resolve(value);
});
}
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
static all(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== "function") {
throw new TypeError(`${array} is not iterable`);
}
let resultArr = [];
let flag = 0;
return new Promise((resolve, reject) => {
if (array.length === 0) {
resolve(array);
return;
}
const processResultByKey = (value, index) => {
resultArr[index] = value;
flag++;
if (flag === array.length) {
resolve(resultArr);
}
};
for (let i = 0; i < array.length; i++) {
let item = array[i];
if (item instanceof Promise) {
item.then(
(r) => {
processResultByKey(r, i);
},
(e) => {
//如果有任何一个promise返回reject,则all直接返回reject
reject(e);
}
);
} else {
//如果不是promise 则异步返回
queueMicrotask(() => {
processResultByKey(item, i);
});
}
}
});
}
static allSettled(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== "function") {
throw new TypeError(`${array} is not iterable`);
}
let resultArr = [];
let flag = 0;
return new Promise((resolve) => {
if (array.length === 0) {
resolve(array);
return;
}
const processResultByKey = (item, index, type) => {
//结果返回对象数组
if (type === 1) {
resultArr[index] = {
status: item.status,
value: item.value,
};
} else {
resultArr[index] = {
status: item.status,
reason: item.reason,
};
}
flag++;
if (flag === array.length) {
resolve(resultArr);
}
};
for (let i = 0; i < array.length; i++) {
let item = array[i];
if (item instanceof Promise) {
item.then(
() => {
processResultByKey(item, i, 1);
},
() => {
processResultByKey(item, i, 2);
}
);
} else {
let p = Promise.resolve(item);
p.then(() => {
processResultByKey(p, i, 1);
});
}
}
});
}
static any(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== "function") {
throw new TypeError(`${array} is not iterable`);
}
let resultArr = [];
let flag = 0;
return new Promise((resolve, reject) => {
if (array.length === 0) {
reject(array);
return;
}
const processResultByKey = (value, index) => {
resultArr[index] = value;
flag++;
if (flag === array.length) {
reject(resultArr, "All promises were rejected");
}
};
for (let i = 0; i < array.length; i++) {
let item = array[i];
if (item instanceof Promise) {
item.then(
(r) => {
//如果有任何一个promise返回resolve,则all直接返回resolve
resolve(r);
},
(e) => {
processResultByKey(e, i);
}
);
} else {
//如果不是promise 则异步返回
queueMicrotask(() => {
processResultByKey(item, i);
});
}
}
});
}
//一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
static race(array) {
//判断iterator类型
if (typeof array[Symbol.iterator] !== "function") {
throw new TypeError(`${array} is not iterable`);
}
return new Promise((resolve, reject) => {
if (array.length === 0) {
return;
}
for (let i = 0; i < array.length; i++) {
let item = array[i];
if (item instanceof Promise) {
item.then(
(r) => {
resolve(r);
},
(e) => {
//如果有任何一个promise返回reject,则all直接返回reject
reject(e);
}
);
} else {
//如果不是promise 则异步返回
queueMicrotask(() => {
resolve(item);
});
}
}
});
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
reject(new TypeError("Chaining cycle detected for promise #<Promise>"));
}
//x是函数或者对象
else if ((typeof x === "object" && x != null) || typeof x === "function") {
//x.then取出或者调用抛出异常返回错误
let called = false; // 标记 resolve或reject只执行一次,优先采用首次调用
try {
let then = x.then;
//如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态
if (typeof then === "function") {
then.call(x,
(y) => {
if (called) return;
called = true;
//thenable 的y可能会返回promise 所有再进一步处理
return resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
}
//then不是函数返回x
else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
}
//x不是函数或者对象
else {
resolve(x);
}
};
Promise.defer = Promise.deferred = function() {
let deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
};
module.exports = Promise;