Использование setInterval в цепочке обещаний, которая использует асинхронное действие Redux-Thunk - PullRequest
0 голосов
/ 26 октября 2019

У меня довольно неясная проблема, и она действительно может возникнуть из-за моих собственных действий, поэтому не стесняйтесь указывать на это, если это так.

У меня есть цепочка обещаний, и мне нужен доступ к промежуточнымзначения для последующих вызовов API. Как только все обещания разрешены, я выполняю вызов API, который использует различные промежуточные возвращаемые значения.

Наконец, основываясь на результатах этого вызова, я делаю последний вызов API. Однако результаты этого вызова используются для обновления состояния Redux и поэтому выполняются с использованием Redux Thunk в качестве промежуточного программного обеспечения для облегчения асинхронных действий.

Проблема заключается в том, что мне необходимо опросить базу данных с заданным интервалом, чтобы проверить, выполнил ли вызов API Redux требуемую работу (это включало в себя размещение некоторых длительных задач в задаче Redis). очереди, а затем попросив работника очереди обновить базу данных после завершения задачи).

Когда база данных подтверждает, что она действительно обновлена ​​с состоянием завершенной задачи, я хочу очистить setIntervalId. Я упростил код до приведенного ниже. Проблема заключается в том, что выполнение не ожидает завершения асинхронного действия Redux. Таким образом, он выполняет действие, а затем переходит к выполнению проверки «if» до того, как действие Redux будет выполнено. Поэтому 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
        })
    };
}


1 Ответ

0 голосов
/ 26 октября 2019

Используйте componentDidUpdate или useEffect

  1. Они будут запускаться всякий раз, когда props.jobStatus обновляет в вашем магазине приставок
  2. Проверьте, что вы taskStatusSuccess(completionStatus) или taskStatusFail(error)отправка с reduxAsyncAction
  3. clearinterval(intId), если статус соответствует

Вам также необходимо добавить intId, чтобы быть в пределах видимости, объявив за пределами callbackFn такойкак:

  • 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])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...