【问题标题】:Handling & Returning Multiple Promises处理和返回多个 Promise
【发布时间】:2018-08-01 10:25:22
【问题描述】:

简要说明

我目前正在努力掌握以下实现的结构:

// Method from API Class (layer for communicating with the API)
call() {
    // Return axios request BUT handle specific API errors e.g. '401 Unauthorized'
    // and prevent subsequent calls to `then` and `catch`
}

// Method from Form Class (used for all forms)
submit() {
    // Call the `call` method on the API class and process
    // the response.
    // IF any validation errors are returned then
    // process these and prevent subsequent calls to `then` 
    // and `catch`
}

// Method on the component itself (unique for each form)
onSubmit() {
    // Call the `submit` method on the Form class
    // Process the response
    // Handle any errors that are not handled by the parent
    // methods
}

我是这样实现的:

// Method from API Class (layer for communicating with the API)
call() {

    // The purpose of this is to execute the API request and return
    // the promise to the caller. However, we need to catch specific
    // API errors such as '401 Unauthorized' and prevent any subsequent
    // `then` and `catch` calls from the caller

    return new Promise((resolve, reject) => {
        this.axios.request(request)
            .then(response => {
                resolve(response); // Do I actually need to do this?
            })
            .catch(error => {

                // Here we need to handle unauthorized errors and prevent any more execution...

                reject(error);
            });
        });
}

// Method from Form Class (used for all forms)
submit() {

    // The purpose of this is to call the API, and then, if it 
    // returns data, or validation errors, process these.

    return new Promise((resolve, reject) => {
        api.call()
            .then(response => {

                // Process form on success
                this.onSuccess(response.data);

                resolve(response.data);
            })
            .catch(error => {

                // Process any validation errors AND prevent
                // any further calls to `then` and `catch` from
                // the caller (the form component)
                this.onFail(error.response.data.error.meta);

                reject(error);
            })
            .then(() => this.processing = false); // This MUST run
        });
}

// Method on the component itself (unique for each form)
onSubmit() {
    this.form.submit()
        .then(response => {

            // This should only run if no errors were caught in
            // either of the parent calls

            // Then, do some cool stuff...
        });
}

问题

我的 cmets 应该解释我想要达到的目标,但要清楚:

  • 如何捕获某些错误,然后防止从调用类/组件运行对 thencatch 的任何进一步调用?
  • 真的有必要每次返回一个new Promise吗?
  • 我知道axios.request 已经返回Promise,但我不知道如何访问resolvereject 方法而不用新的Promise 包装它。如有错误,欢迎指正...

【问题讨论】:

  • 避免使用promise anti-pattern。你可以做return this.axios.request(request).catch(...)
  • @jfriend00 这就是我问这个问题的原因之一,我讨厌我上面的代码,我知道这很糟糕,但我不知道解决方案是什么.你能开导我吗?
  • "和防止后续调用thencatch" 是什么意思?您的函数正在返回承诺。根据定义,thencatch 处理程序将运行。
  • @jfriend00 这就是我之前尝试做的事情,但后来我遇到了从调用类调用catchthen 的问题。有没有办法终止承诺?
  • 嗯,你的一堆问题没有意义,这就是我没有尝试回答的原因。正如 TJ 所说,如果你返回一个承诺,你不会阻止 .then().catch() 处理程序运行。相反,您训练调用代码执行什么操作以及跳过什么,并确保您设置了一个已解决的值或拒绝导致调用者做正确事情的原因。

标签: javascript ecmascript-6 promise es6-promise


【解决方案1】:

首先:当您已经有合作承诺时,就不需要new Promise。所以作为第一步,让我们修复(比如说)call

call() {
    return this.axios.request(request)
        .then(response => {
            // ...
        })
        .catch(error => {
            // ...
        });
}

如何捕获某些错误,然后防止从调用类/组件运行对 thencatch 的任何进一步调用?

你没有。如果您要返回一个承诺,它必须解决(解决或拒绝)。要么涉及后续处理程序的运行。承诺就是这样:承诺,您将提供一个值(解决方案)或一个错误(拒绝)。

您可能缺少的关键概念(很多人都这样做!)是 thencatch 返回 new 承诺,这些承诺会根据其处理程序的行为来解决/拒绝。

您可以使用catch 处理程序来:

  1. 将拒绝转化为解决方案
  2. 将一个错误的拒绝转换为另一个错误的拒绝
  3. 结果完全基于另一个承诺的结果

...但您不能禁止对后续回调的调用。

您可以使用then 处理程序来:

  1. 将具有一个值的分辨率转换为具有另一个值的分辨率
  2. 将解决转化为拒绝
  3. 结果完全基于另一个承诺的结果

因此,例如,如果您有可以纠正的错误情况(这种情况比较少见,但确实会发生),您可以这样做

.catch(error => {
   if (/*...the error can be corrected...*/) {
        return valueFromCorrectingTheProblem;
   }
   throw error; // Couldn't correct it
})

如果您返回一个值(或解析的承诺),catch 返回的承诺将使用该值解析。如果你抛出(或返回一个拒绝的承诺),catch 返回的承诺会拒绝。

真的有必要每次返回一个新的 Promise 吗?

不,见上文。 (这是个好问题。)

我知道 axios.request 已经返回了一个 Promise,但我不知道如何访问 resolvereject 方法而不用新的 Promise 包装它。

你没有;你使用thencatch。它们返回一个 new 承诺,该承诺将根据处理程序中发生的情况被解决/拒绝。

【讨论】:

  • 这是一个完美的解释TJ,非常感谢!真的很感激!如果我有任何问题,我将再次执行我的实施并回来,但这似乎涵盖了我需要的一切:-D
猜你喜欢
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 2020-04-22
相关资源
最近更新 更多