当前位置:  开发笔记 > 编程语言 > 正文

在复杂的承诺返回链中承诺catch()顺序

如何解决《在复杂的承诺返回链中承诺catch()顺序》经验,为你挑选了1个好方法。

如果我从函数A向函数B返回一个promise,从A返回数据,并且两个调用都捕获了Promise,那么错误如何被捕获?我知道,当承诺得到解决时,A然后总是首先被执行,然后是B,然后是从A返回的数据.但是,当Promises的这种返回形成一个长链时,我无法理解错误是如何被捕获的.以下是该场景的简化示例.我正在使用Redux-thunk动作创建器来管理状态.

function postActionCreator(data) {
  return (dispatch) => {
    dispatch(type: POST_LOADING)
    return Source.post()
      .then(response => {
        dispatch(type: POST_SUCCESS, payload: response)
        return response
      })
      .catch(error => {
        // Is this catch called if handlePost throws error in then?
        dispatch(type: POST_ERROR, payload: error)
        throw new Error(error)
      })
  }
}

// Container component's post function calling the Redux action creator
function handlePost(data) {
  this.props.postActionCreator(data)
    .then(response => {
      // Do something with response
    })
    .catch(error => {
      // Or is the error caught with this catch?
    })
}

// Or are the both catchs called, in which order and why?

如何在这三种不同的场景中处理错误:

Source.post抛出并出错

postActionCreator然后抛出一个错误

handlePost然后抛出一个错误

Will Demaine.. 5

使用promises时,函数应该执行以下三种操作之一:

    返回一个值

    回报承诺

    抛出一个错误

对于这个问题,我们并不太关心前两种情况,但您可以在此处阅读有关承诺解决程序的更多信息.那么让我们来看一下这个错误案例.

在JavaScript中,错误 - 就像大多数事情一样 - 只是对象.创建错误并选择如何传播该错误是两回事.传播错误的两大类是同步和异步的.要同步传播错误,您必须throw为异步,只需通过某些预定义约定(例如回调或承诺)传递错误对象.

要完全回答这个问题,我们需要了解如何处理这两种不同的错误类型.对于同步错误(已抛出),处理它们的唯一方法(除了捕获所有事件处理程序之外window.onerror)是将它们包装在try/catch语句中.对于异步错误,我们只遵循如何将这些数据传递回调用堆栈的约定.

所以用这些知识回答你的问题:

Source.post抛出错误

如果我假设"抛出一个错误"你的意思是"发生了错误",我们无法知道在不知道源代码的情况下这将如何表现Source.post.如果实际上抛出了一个错误,让我们说有一些意想不到的错误ReferenceError,那么它根本就不会被处理掉:

function post() {
  foo.bar; // will throw
}

function run() {
  post()
    .then(log)
    .catch(log);
}

会导致:

ReferenceError: foo is not defined
    at post (sync.js:6:3)
    at run (sync.js:10:3)
    at Object. (sync.js:15:1)

现在,如果post函数实际异步处理错误,在这种情况下通过确认传递错误的promise约定,我们会看到它会被捕获:

function post() {
  return new Promise((resolve, reject) => {
    reject('foo');
  });
}

function run() {
  post()
    .then(() => {})
    .catch((err) => {
      console.error('Caught error:', err);
    });
}

结果是

Caught error: foo

另一个有趣的部分是,您的代码在catch语句中实际抛出了一个新Error对象.在这种情况下,我们最后要了解一件事.我们知道同步抛出错误意味着它必须被捕获,但是在then函数内抛出错误会导致被拒绝的异常,而不是错误,所以发生了什么?那么,承诺实现内部包裹你传递给函数then在一个try/catch块,然后通过拒绝承诺处理这个错误.我们可以证明这样:

function post() {
  return new Promise((resolve, reject) => {
    resolve('foo');
  });
}

function run() {
  post()
    .then((result) => {
      throw result;
    })
    .catch((err) => {
      console.error('Caught error:', err);
    });
}

在这种情况下,也会捕获错误.

postActionCreator然后抛出一个错误

现在变得简单了.then捕获并传播a中的错误.它到达catch内部postActionCreator然后被重新投入到外面catch.

handlePost然后抛出一个错误

最简单的情况.它会被内部捕获,你会在catch声明后立即得到错误then.


最后,你可能会想,"我怎么能处理那些同步错误Source.post?如果那不是我的功能怎么办?".好问题!您可以使用Bluebird的promise.try之类的实用程序为您包装此函数.



1> Will Demaine..:

使用promises时,函数应该执行以下三种操作之一:

    返回一个值

    回报承诺

    抛出一个错误

对于这个问题,我们并不太关心前两种情况,但您可以在此处阅读有关承诺解决程序的更多信息.那么让我们来看一下这个错误案例.

在JavaScript中,错误 - 就像大多数事情一样 - 只是对象.创建错误并选择如何传播该错误是两回事.传播错误的两大类是同步和异步的.要同步传播错误,您必须throw为异步,只需通过某些预定义约定(例如回调或承诺)传递错误对象.

要完全回答这个问题,我们需要了解如何处理这两种不同的错误类型.对于同步错误(已抛出),处理它们的唯一方法(除了捕获所有事件处理程序之外window.onerror)是将它们包装在try/catch语句中.对于异步错误,我们只遵循如何将这些数据传递回调用堆栈的约定.

所以用这些知识回答你的问题:

Source.post抛出错误

如果我假设"抛出一个错误"你的意思是"发生了错误",我们无法知道在不知道源代码的情况下这将如何表现Source.post.如果实际上抛出了一个错误,让我们说有一些意想不到的错误ReferenceError,那么它根本就不会被处理掉:

function post() {
  foo.bar; // will throw
}

function run() {
  post()
    .then(log)
    .catch(log);
}

会导致:

ReferenceError: foo is not defined
    at post (sync.js:6:3)
    at run (sync.js:10:3)
    at Object. (sync.js:15:1)

现在,如果post函数实际异步处理错误,在这种情况下通过确认传递错误的promise约定,我们会看到它会被捕获:

function post() {
  return new Promise((resolve, reject) => {
    reject('foo');
  });
}

function run() {
  post()
    .then(() => {})
    .catch((err) => {
      console.error('Caught error:', err);
    });
}

结果是

Caught error: foo

另一个有趣的部分是,您的代码在catch语句中实际抛出了一个新Error对象.在这种情况下,我们最后要了解一件事.我们知道同步抛出错误意味着它必须被捕获,但是在then函数内抛出错误会导致被拒绝的异常,而不是错误,所以发生了什么?那么,承诺实现内部包裹你传递给函数then在一个try/catch块,然后通过拒绝承诺处理这个错误.我们可以证明这样:

function post() {
  return new Promise((resolve, reject) => {
    resolve('foo');
  });
}

function run() {
  post()
    .then((result) => {
      throw result;
    })
    .catch((err) => {
      console.error('Caught error:', err);
    });
}

在这种情况下,也会捕获错误.

postActionCreator然后抛出一个错误

现在变得简单了.then捕获并传播a中的错误.它到达catch内部postActionCreator然后被重新投入到外面catch.

handlePost然后抛出一个错误

最简单的情况.它会被内部捕获,你会在catch声明后立即得到错误then.


最后,你可能会想,"我怎么能处理那些同步错误Source.post?如果那不是我的功能怎么办?".好问题!您可以使用Bluebird的promise.try之类的实用程序为您包装此函数.

推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有