在React中使用动作减少器链接承诺

时间:2019-01-09 15:16:10

标签: javascript reactjs redux promise

我有一种方法可以向API触发两个http请求以获取数据。

getServerDetails(this.props.match.params.id) //1
            .then(res => {
                this.props.getServerDetailsAction({ success: true, data: res.data })

                if (!_.isEmpty(res.data)) {
                    return getServerScomAlerts(res.data.ServerName) //2
                }
            })
            .catch((err) => { //3
                this.props.getServerDetailsAction({ success: false, error: err })
            })
            .then(res => {
                if (!_.isEmpty(res)) {
                    this.props.getServerScomAlertsAction({ success: true, data: res.data })
                }
            })
            .catch((err) => { //4
                this.props.getServerScomAlertsAction({ success: false, error: err })
            })

getServerDetails (1)getServerScomAlerts (2)方法正在返回promise。 getServerScomAlerts (2)取决于getServerDetails (1)

的结果

问题在于,如果在getServerScomAlerts (2)中发生错误,则会执行第一个catch块(3)。有没有一种方法可以从第一种方法(1) 不访问商店 )获取数据,并同时跳转到相应的catch块{{ 1}}如果发生错误?

3 个答案:

答案 0 :(得分:1)

类似的事情可能会让您了解如何实现自己的目标。您可以使用async / await而不是嵌套的方式,它先等待每个调用的结果,然后再进行下一个操作:

export const actionCreators = {
    myFunc: (param1, param2) => async (dispatch, getState) => {
        try {
            const response1 = await fetch(param1);
            const data1 = await response.json();

            const response2 = await fetch(param2);
            const data2 = await response2.json();

        } catch (err) {
            console.log(err);
        }
    }
}

答案 1 :(得分:0)

您的问题真的很有趣,因为您想执行多个仅略有不同的动作:)。我将重写如下

const getServerScomAlertsAction = (success, props) => (res) => {
  success = success && !_.isEmpty(res);
  props.getServerScomAlertsAction(success ? { success, data: res.data } : { success, error: res });
};
const getServerDetailsAction = (success, props) => (res) => {
  props
    .getServerDetailsAction(success ? { success, data: res.data } : { success, error: res })
    .then(getServerScomAlertsAction(true, props))
    .catch(getServerScomAlertsAction(false, props));
};

getServerDetails(this.props.match.params.id)
  .then(getServerDetailsAction(true, this.props))
  .catch(getServerDetailsAction(false, this.props));

答案 2 :(得分:0)

这是.finally()方法的一个很好的用例,目前在MDN的规范草案中。它可以让您在承诺被解决或拒绝后通过运行方法来删除重复逻辑。

如MDN示例所示:

let isLoading = true;

fetch(myRequest).then(function(response) {
    var contentType = response.headers.get("content-type");
    if(contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
  })
  .then(function(json) { /* process your JSON further */ })
  .catch(function(error) { console.log(error); /* this line can also throw, e.g. when console = {} */ })
  .finally(function() { isLoading = false; });

如果您想立即使用此功能,可以考虑使用Bluebird来实现承诺,这在某些情况下会更快,并且随着方法的标准化也应易于升级