文章目录
前言
我们在上篇用了很大功夫实现了 Promise 的核心方法,并且通过了 Promises/A+ 官方872个测试用例测试,接下来实现这些静态方法已经是小菜一碟了,因为这些 API 全部是对前面的封装而已。
上篇文章在这里:手把手一行一行代码教你“手写Promise“,完美通过 Promises/A+ 官方872个测试用例
官方 Promise 还有很多API ,除了 then 方法以外还有 两个实例方法:
- Promise.prototype.catch
- Promise.prototype.finally
◾ 以及目前 Promise 规范的 六个静态方法:
- Promise.resolve
- Promise.reject
- Promise.all
- Promise.allSettled
- Promise.any
- Promise.race
虽然这些都不在 Promise/A+ 规范里面,但是我们也来实现一下吧,加深理解。其实我们前面我们用了很大功夫实现了 Promise/A+ ,现在再来实现这些已经是小菜一碟了,因为这些API全部是前面的封装而已。
1. 实现 Promise.resolve
Promise.resolve(value) 将给定的一个值转为Promise对象。
- 如果这个值是一个 promise ,那么将返回这个 promise ;
- 如果这个值是thenable(即带有
"then"
方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态; - 否则返回的promise将以此值完成,即以此值执行
resolve()
方法 (状态为fulfilled)。
根据规范我们这样实现(写法一):
class myPromise {
...
}
function resolvePromise(promise2, x, resolve, reject) {
...
}
/**
* Promise.resolve()
* @param {[type]} value 要解析为 Promise 对象的值
*/
+ myPromise.resolve = function (value) {
+ // 如果这个值是一个 promise ,那么将返回这个 promise
+ if (value instanceof myPromise) {
+ return value;
+ } else if (value instanceof Object && 'then' in value) {
+ // 如果这个值是thenable(即带有`"then" `方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
+ return new myPromise((resolve, reject) => {
+ value.then(resolve, reject);
+ })
+ }
+
+ // 否则返回的promise将以此值完成,即以此值执行`resolve()`方法 (状态为fulfilled)
+ return new myPromise((resolve) => {
+ resolve(value)
+ })
+ }
module.exports = myPromise;
使用官方例子测试一下:
const myPromise = require('./promiseOtherAPI');
const promise1 = myPromise.resolve(123);
promise1.then((value) => {
console.log(value);
// expected output: 123
});
// Resolve一个thenable对象
var p1 = myPromise.resolve({
then: function (onFulfill) {
onFulfill("Resolving");
}
});
console.log(p1 instanceof myPromise) // true, 这是一个Promise对象
setTimeout(() => {
console.log('p1 :>> ', p1);
}, 1000);
p1.then(function (v) {
console.log(v); // 输出"fulfilled!"
}, function (e) {
// 不会被调用
});
// Thenable在callback之前抛出异常
// myPromise rejects
var thenable = {
then: function (resolve) {
throw new TypeError("Throwing");
resolve("Resolving");
}
};
var p2 = myPromise.resolve(thenable);
p2.then(function (v) {
// 不会被调用
}, function (e) {
console.log(e); // TypeError: Throwing
});
输出结果:
true
123
Resolving
TypeError: Throwing
p1 :>> myPromise {
PromiseState: 'fulfilled', PromiseResult: 'Resolving', onFulfilledCallbacks: Array(1), onRejectedCallbacks: Array(1)}
测试通过 ✌
静态方法改造
类(class)通过 static 关键字定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。这些通常是实用程序方法,例如创建或克隆对象的功能。
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
写法二、使用静态方法 static:
class myPromise {
...
resolve(result) {
...
}
reject(reason) {
...
}
then(onFulfilled, onRejected) {
...
}
/**
* Promise.resolve()
* @param {[type]} value 要解析为 Promise 对象的值
*/
+ static resolve(value) {
+ // 如果这个值是一个 promise ,那么将返回这个 promise
+ if (value instanceof myPromise) {
+ return value;
+ } else if (value instanceof Object && 'then' in value) {
+ // 如果这个值是thenable(即带有`"then" `方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
+ return new myPromise((resolve, reject) => {
+ value.then(resolve, reject);
+ })
+ }
+
+ // 否则返回的promise将以此值完成,即以此值执行`resolve()`方法 (状态为fulfilled)
+ return new myPromise((resolve) => {
+ resolve(value)
+ })
+ }
}
function resolvePromise(promise2, x, resolve, reject) {
...
}
module.exports = myPromise;
2. 实现 Promise.reject
Promise.reject()
方法返回一个带有拒绝原因的Promise
对象。
官方例子:
Promise.reject(new Error('fail')).then(function() {
// not called
}, function(error) {
console.error(error); // Stacktrace
});
输出结果:
根据规范我们这样实现(写法一):
class myPromise {
...
}
function resolvePromise(promise2, x, resolve, reject) {
...
}
myPromise.resolve = function (value) {
...
}
/**
* myPromise.reject
* @param {*} reason 表示Promise被拒绝的原因
* @returns
*/
+ myPromise.reject = function (reason) {
+ return new myPromise((resolve, reject) => {
+ reject(reason);
+ })
+ }
module.exports = myPromise;
使用官方用例测试一下:
const myPromise = require('./promiseOtherAPI')
myPromise.reject(new Error('fail')).then(function () {
// not called
}, function (error) {
console.error(error); // Error: fail
});
输出结果:
Error: fail
测试通过 ✌
写法二、使用静态方法 static:
class myPromise {
...
resolve(result) {
...
}
reject(reason) {
...
}
then(onFulfilled, onRejected) {
...
}
/**
* Promise.resolve()
* @param {[type]} value 要解析为 Promise 对象的值
*/
static resolve(value) {
// 如果这个值是一个 promise ,那么将返回这个 promise
if (value instanceof myPromise) {
return value;
} else if (value instanceof Object && 'then' in value) {
// 如果这个值是thenable(即带有`"then" `方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
return new myPromise((resolve, reject) => {
value.then(resolve, reject);
})
}
// 否则返回的promise将以此值完成,即以此值执行`resolve()`方法 (状态为fulfilled)
return new myPromise((resolve) => {
resolve(value)
})
}
/**
* myPromise.reject
* @param {*} reason 表示Promise被拒绝的原因
* @returns
*/
+ static reject(reason) {
+ return new myPromise((resolve, reject) => {
+ reject(reason);
+ })
+ }
}
function resolvePromise(promise2, x, resolve, reject) {
...
}
module.exports = myPromise;
3. 实现 Promise.prototype.catch
catch()
方法返回一个Promise
,并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected)
相同。
事实上, calling obj.catch(onRejected)
内部calls obj.then(undefined, onRejected)
。(这句话的意思是,我们显式使用obj.catch(onRejected)
,内部实际调用的是obj.then(undefined, onRejected)
)
Promise.prototype.catch()
方法是.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
因此我们可以这样来实现:
class myPromise {
...
then(onFulfilled, onRejected) {
...
}
+ catch (onRejected) {
+ return this.then(undefined, onRejected)
+ }
}
function resolvePromise(promise2, x, resolve, reject) {
...
}
module.exports = myPromise;
就一行代码,我的天,居然这么简单😱
我们用官方例子来测试一下吧
const myPromise = require('./promiseOtherAPI')
var p1 = new myPromise(function (resolve, reject) {
resolve('Success');
});
p1.then(function (value) {
console.log(value); // "Success!"
throw 'oh, no!';
}).catch(function (e) {
console.log(e); // "oh, no!"
}).then(function () {
console.log('after a catch the chain is restored');
}, function () {
console.log('Not fired due to the catch');
});
// 以下行为与上述相同
p1.then(function (value) {
console.log(value); // "Success!"
return Promise.reject('oh, no!');
}).catch(function (e) {
console.log