首页 文章

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

提问于
浏览
0

我有这个ES6代码调用java后端 . 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的参数,响应是反序列化的对象 . 好 .

  • But ,函数D中的参数,响应不是反序列化的对象,而是反序列化对象的承诺 .

我已经在这方面工作了一段时间,但我很难解释谷歌我的问题是什么 .

Question: 为什么返回一个承诺'unwrap'下一个函数的承诺,但抛出一个承诺将承诺本身传递给下一个函数?

有没有什么方法可以实现我想要的,这是函数D得到'解包'对象就像函数C一样?

1 回答

  • 3

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

    对于 thencatch 回调中的返回值,规则是该promise必须在外部promise解析之前解析,并且已解析的值应该是返回的promise承诺的值 . 来自Promises/A+ specs 2.2.7.1

    如果onFulfilled或onRejected返回值x,请运行Promise Resolution Procedure [[Resolve]](promise2,x) .

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

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

    如果onFulfilled或onRejected引发异常e,则必须拒绝promise2,并将e作为原因 .

    没有试图承认 e 是承诺,也不是等待其解决 . 它按原样抛出,这将是你在下一个 catch 得到的 .

    解决方案

    因此,解决方案是返回一个promise,但是一个将抛出已解析值(而不是promise)的promise:

    return response.json().then(data => { throw data });
    

相关问题