在使用 Redux-Thunk 异步操作的 Promise 链中使用 setInterval
Posted
技术标签:
【中文标题】在使用 Redux-Thunk 异步操作的 Promise 链中使用 setInterval【英文标题】:Using setInterval in promise chain which uses Redux-Thunk async action 【发布时间】: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 回调中忽略它
【参考方案1】:
使用componentDidUpdate
或useEffect
-
只要
props.jobStatus
在您的 redux 存储中更新,这些就会运行
检查您从reduxAsyncAction
发送的taskStatusSuccess(completionStatus)
或taskStatusFail(error)
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 语句之前没有完全完成的问题。 我更新了我的答案,我相信会更清楚。让我知道我是否仍然错过了标记,干杯!以上是关于在使用 Redux-Thunk 异步操作的 Promise 链中使用 setInterval的主要内容,如果未能解决你的问题,请参考以下文章
redux-thunk:错误:动作必须是普通对象。使用自定义中间件进行异步操作