【问题标题】:Using setInterval in promise chain which uses Redux-Thunk async action在使用 Redux-Thunk 异步操作的 Promise 链中使用 setInterval
【发布时间】:2020-02-22 06:02:04
【问题描述】:

我有一个相当模糊的问题,它确实可能是我自己的问题,如果是这样,请随时指出。

我有一个承诺链,我需要访问中间值以进行后续 API 调用。一旦所有承诺都得到解决,我就会执行一个 API 调用,该调用利用各种中间返回值。

最后,根据该调用的结果,我对 API 进行最终调用。但是,此调用的结果用于更新 Redux 状态,因此使用 Redux Thunk 作为中间件来促进异步操作。

挑战出现在我需要以设定的时间间隔轮询数据库以检查 Redux API 调用是否执行了它所请求的工作(这涉及在 Redis 任务队列中放置一些长时间运行的任务,然后任务完成后让队列工作人员更新数据库)。

当数据库确认确实已更新完成任务状态时,我想清除setIntervalId。我已将代码简化为如下所示。问题是执行不会等待 Redux 异步操作完成。因此,它执行该操作,然后在 Redux 操作完成之前直接执行“if”检查。因此 if 永远不会为真,并且轮询会无限期地继续。

我不知道如何确保 Redux Action 在代码继续之前完成。我已经精简了代码以使逻辑到位,而不会用不相关的代码过度拥挤这篇文章。

有什么想法可以让它按预期工作吗?

buttonClickedHandler.js

callbackFn {function(){
    const a = ApiCallA(...) // Returns a promise

    const b = a.then(resA => {
        // Some work done here
        return ApiCallB(…); // Returns a promise

    const c = b.then(resB => {
        // Some work done here
        return ApiCallC(…); // Returns a promise  

    return Promise.all( ([a, b, c] )
        .then( ([resA, resB, resC] ) => {
            // Some work done here
            return ApiCallD
        })
        .then( resD => {
            const intId = setInterval( () => {
                reduxAsyncAction(resD.jobId) // <-- This makes a final API call
                    if (props.jobStatus){ // <-- jobStatus gets updated too late
                         clearInterval(intId ); 
                    }
                }, 5000)
          })
         .catch(err => console.log(err))
}

redux action creator

export const reduxAsyncAction= (jobId) => {
    return dispatch => {
        dispatch(taskStatusStart()); // <- Basic sync. action creator
        return databaseQuery() // Returns Promise therefore pushed to taskqueue while other function run
        .then(dbData=>{
            const completionStatus = dbData.status; // <- True or False
            dispatch(taskStatusSuccess(completionStatus)) // <- Basic sync. action creator
        },
        error => {
            dispatch(taskStatusFail(error)); // <- Basic sync. action creator
        })
    };
}


【问题讨论】:

  • 我不知道 reactjs/redux 的来龙去脉——我所知道的是你的 reduxAsyncAction 函数返回一个 Promise,你基本上不会在那个 setInterval 回调中忽略它

标签: javascript reactjs promise react-redux redux-thunk


【解决方案1】:

使用componentDidUpdateuseEffect

  1. 只要 props.jobStatus 在您的 redux 存储中更新,这些就会运行
  2. 检查您从reduxAsyncAction 发送的taskStatusSuccess(completionStatus)taskStatusFail(error)
  3. clearinterval(intId) 如果状态匹配

您还需要通过在callbackFn 之外声明,将intId 添加到范围内,例如:

  • this.intId 在基于类的组件的构造函数中

  • let intId 在功能组件的顶部。

基于类的组件:

componentDidUpdate(){
    if (intId && props.jobStatus === 'completionStatus' || props.jobStatus === 'error'){
          clearInterval(intId); 
          intId = null;
    } 
}

功能组件:

useEffect(()=>{
    if (intId && props.jobStatus === 'completionStatus' || props.jobStatus === 'error'){
        clearInterval(intId); 
        intId = null;
    } 
},[props.jobStatus])

【讨论】:

  • 你好威廉。感谢您的回复。不幸的是,这仍然给我留下了异步 redux thunk 调用在执行 if 语句之前没有完全完成的问题。
  • 我更新了我的答案,我相信会更清楚。让我知道我是否仍然错过了标记,干杯!
猜你喜欢
  • 2018-01-31
  • 2021-10-04
  • 2017-03-03
  • 2020-01-17
  • 1970-01-01
  • 2016-09-19
  • 2018-02-28
  • 2016-12-20
  • 2021-09-14
相关资源
最近更新 更多