原文链接https://jakearchibald.com/2014/resolve-not-opposite-of-reject/
第一次把Promise用在工作中时,我对它抱有这样一种简单的看法:把一个值传入reject()
函数,这个promise就“失败”了;而把一个值传入resolve()
函数那它就“成功”了。但是,后者却并不总是对的。
new Promise(function(resolve, reject) {
resolve(something);
}).then(function() {
console.log("Yey");
}, function() {
console.log("Boo");
});
我们并没有调用reject()
函数,但当以下情况出现时,作为rejection回调的console.log("Boo");
还是会被调用:
- 参数
something
没有被定义。这样会导致错误的抛出,这个错误将被promise捕捉然后传入reject()
,或者 - 参数
something
是一个rejected状态的promise对象
于是:
new Promise(function(resolve, reject) {
resolve(Promise.reject());
}).catch(function() {
// 这个函数会被调用
});
这是一件好事,因为它的行为和Promise.resolve()
,还有回调函数的返回值的行为一样:
var promise1 = Promise.resolve(Promise.reject());
var promise2 = Promise.resolve().then(function() {
return Promise.reject();
});
var promise3 = Promise.reject().catch(function() {
return Promise.reject();
});
上面的三个promise都将变成rejected状态,当你用then()
方法去解析一个值时,你将会把这个操作推迟到最后一个非promise值(译注:此处原文When you resolve a value with a "then" method, you're deferring the resolution to the eventual non-promise value.)
(译注:这些代码无法运行。原文评论区一位同学说明,如果一个Promise对象不立即调用then()
或catch()
函数,浏览器将会抛出错误。他建议使用如下代码:
var promise1 = Promise.resolve(Promise.reject()).then(() => {}, (err) => {
console.log(err); //undefined
});
var promise2 = Promise.resolve().then(function() {
return Promise.reject();
}).catch((err) => {
console.log(err); //undefined
});
var promise3 = Promise.reject().catch(function() {
return Promise.reject();
}).then(() => {}, (err) => {
console.log(err); //undefined
});
这些代码也印证了作者的看法)
实践
根据Promise的这些特性,你完全可以去解析一个值而不必担心它到底是一个值呢,还是一个Promise呢,还是一个解析解析Promise的Promise的Promise呢,等等等等。(译注:2333,原文or a promise that resolves to a promise that resolves to a promise etc etc.)
function apiCall(method, params) {
return new Promise(function(resolve, reject) {
if (!method) {
throw TypeError("apiCall: You must provide a method");
}
var data = {
jsonrpc: "2.0",
method: method
}
if (params) {
data.params = params;
}
resolve(postJSON('/my/api/', data));
});
}
现在不管是参数method
没有传入,还是postJSON()
方法被拒绝,又或者因为一些别的啥原因,apiCall
都会reject()。你其实用Promise
方案安全地封装了postJSON
方法。