[译]Promise:Resolve 并不是 Reject 的对立面 - Jake Archibald

原文链接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方法。

你可能感兴趣的:([译]Promise:Resolve 并不是 Reject 的对立面 - Jake Archibald)