【问题标题】:Chaining promises with action reducers in React在 React 中使用 action reducer 链接 promise
【发布时间】:2019-01-10 01:44:44
【问题描述】:

我有一个方法向 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) 方法正在返回承诺。 getServerScomAlerts (2) 依赖于getServerDetails (1) 的结果

问题是如果getServerScomAlerts (2) 发生错误,第一个catch 块(3) 会被执行。有没有办法从第一种方法(1)(无需访问商店)获取数据,同时跳转到相应的catch块(4) if发生错误?

【问题讨论】:

  • 您可以考虑将async/await 与传统的try {} catch {} 块一起使用,以便对此进行更多控制。

标签: javascript reactjs redux promise


【解决方案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);
        }
    }
}

【讨论】:

    【解决方案2】:

    你的问题真的很有趣,因为你想做多个彼此略有不同的动作:)。我会重写如下

    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));
    

    【讨论】:

      【解决方案3】:

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

      如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 来实现您的承诺,在某些情况下更快,并且由于方法标准化,应该易于升级

      【讨论】:

        猜你喜欢
        • 2017-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-16
        • 2018-11-08
        • 2016-08-16
        相关资源
        最近更新 更多