处理&回归多重承诺

时间:2018-02-21 18:07:27

标签: javascript ecmascript-6 promise es6-promise

简要说明

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

// 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...
        });
}

问题

我的评论应该解释我想要实现的目标,但要明确:

  • 如何捕获某些错误,然后阻止对thencatch的任何进一步调用从调用类/组件运行?
  • 每次返回时,是否真的有必要创建new Promise
  • 我知道axios.request已经返回Promise但我不知道如何访问resolvereject方法,而不用新的Promise {1}}。如果这是错误的,请随时纠正...

1 个答案:

答案 0 :(得分:4)

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

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

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

你没有。如果您要退回承诺,则必须解决(解决或拒绝)。要么涉及后续处理程序运行。承诺正是如此:承诺您要么提供值(分辨率)要么提供错误(拒绝)。

您可能遗漏的关键概念(很多人都这么做!)是thencatch返回承诺,根据他们的承诺解决/拒绝承诺处理程序。

您可以使用catch处理程序:

  1. 将拒绝转换为解决方案
  2. 将带有一个错误的拒绝转换为另一个错误的拒绝
  3. 将结果完全基于另一个承诺的结果
  4. ...但你无法抑制对后续回调的调用。

    您可以使用then处理程序:

    1. 将具有一个值的分辨率转换为具有其他值的分辨率
    2. 将分辨率转换为拒绝
    3. 将结果完全基于另一个承诺的结果
    4. 因此,例如,如果您有错误条件可以纠正(这种情况相对较少,但发生了),您可以这样做

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

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

        

      每次返回时,是否真的有必要创建一个新的Promise?

      不,见上文。 (还有好问题。)

        

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

      你没有;您使用thencatch。他们返回新的承诺,根据处理程序中发生的情况解决/拒绝承诺。