ES6承诺 - 为什么从catch()抛出并从then()抛出的行为不一样?

时间:2017-08-25 22:32:57

标签: promise es6-promise

我有一段调用java后端的ES6代码。 java后端通常返回状态代码200和json有效负载,但有时返回状态代码500和json有效负载。对于200,我想反序列化json并将结果对象传递给promise链。对于500,我想反序列化json并将抛出结果对象带到promise链上,即让它击中catch块。

以下代码几乎可以满足我的需求:

invoke(className, methodName, args) {
    return this.httpClient
        .fetch('/api/' + className + "/" + methodName,
            {
                method: 'POST',
                body: json(args)
            })
        .catch(response => {
            // Function A
            throw response.json();
        })
        .then(response => {
            // Function B
            return response.json();
        });
}

this.invoke("TestService", "testMethod", {a: 1, b: 2})
    .then(response => {
        // Function C
        console.log(response); // prints the actual json object which I expect
    }).catch(response => {
        // Function D
        console.log(response); // prints: [object Promise]
    });
  • 功能A被调用500.好。
  • 函数B调用200.好。
  • response.json()返回A和B中反序列化对象的承诺。好。
  • 函数A导致函数D被调用。好。
  • 函数B导致调用函数C.好。
  • 函数C的参数,响应是反序列化的对象。好。
  • 但是,函数D中的参数,响应不是反序列化的对象,而是反序列化对象的承诺。

我已经在这方面工作了一段时间,但我在解释谷歌问题时遇到了问题。

问题:为什么要回复承诺'展开'下一个函数的承诺,但抛出一个承诺将承诺本身传递给下一个函数?

有什么方法可以达到我想要的效果,这是因为功能D可以让你解开'对象就像函数C?

1 个答案:

答案 0 :(得分:3)

你在catch回调中得到承诺的原因是这是规范。

对于<{1}}或then回调中返回的值,规则是该promise必须在外部promise解析之前解析,并且解析后的值应为返回的承诺承诺的价值。来自Promises/A+ specs 2.2.7.1

  

如果catchonFulfilled返回值onRejected,请运行承诺解决程序x

该规范中的第3章进一步解释了这意味着什么。

但是,抛出异常并非如此,如point 2.2.7.2中所示:

  

如果[[Resolve]](promise2, x)onFulfilled引发异常onRejected,则必须以e为由拒绝promise2。

不会尝试将e视为承诺,也不会等待其解决。它按原样抛出,这将是你在下一个e中得到的结果。

解决方案

因此,解决方案是返回一个承诺,但承诺会抛出已解决的值(而不是承诺):

catch