реагировать на редукцию - применение выборки и отправки внутри отправки не удается

У меня есть рабочее действие, которое сохраняет токен JWT с помощью простого вызова «saveJwt (данные)».

Вот действие:

export const requestLoginToken = (username, password) =>
  (dispatch, getState) => {
    dispatch({type: REQUEST_LOGIN_TOKEN, payload: username})

    const payload = {
      userName: username,
      password: password,
    }

    const task = fetch('/api/jwt', {
      method: 'POST',
      body: JSON.stringify(payload),
      headers: {
        'Content-Type': 'application/json;charset=UTF-8'
      },
    })
      .then(handleErrors)
      .then(response => response.json())
      .then(data => {
        dispatch({type: RECEIVE_LOGIN_TOKEN, payload: data})
        saveJwt(data)
      })
      .catch(error => {
        clearJwt()
        dispatch({type: ERROR_LOGIN_TOKEN, payload: error.message})
      })
    addTask(task)
    return task
  }

Затем я добавил прямо под «saveJwt (данные)». Этот блок кода:

    if (!confirmSelectDataExistance()) {
      dispatch({ type: REQUEST_SELECT_DATA })
      const token = getJwt()
      const headers = new Headers({
        'Authorization': `Bearer ${token}`
      })
      const retrieveSelectData = fetch('/api/SelectData/SelectData', {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json;charset=UTF-8'
        },
      })
        .then(handleErrors)
        .then(response => response.json())
        .then(selectData => {
          dispatch({ type: RECEIVE_SELECT_DATA, payload: selectData })
          saveSelectData(selectData)
        })
   }

Все, что он должен сделать, это проверить, находятся ли элементы в локальном хранилище, и если да, то на этот раз выполнить еще одну выборку с добавлением JWT.

Вот завершенное действие, чтобы вы могли видеть, где оно находится:

export const requestLoginToken = (username, password) =>
  (dispatch, getState) => {
    dispatch({ type: REQUEST_LOGIN_TOKEN, payload: username })

    const payload = {
      userName: username,
      password: password,
    }

    const task = fetch('/api/jwt', {
      method: 'POST',
      body: JSON.stringify(payload),
      headers: {
        'Content-Type': 'application/json;charset=UTF-8'
      },
    })
      .then(handleErrors)
      .then(response => response.json())
      .then(data => {
        dispatch({ type: RECEIVE_LOGIN_TOKEN, payload: data })
        saveJwt(data)
        //selectData download if nothing is local storage.
        if (!confirmSelectDataExistance()) {
          dispatch({ type: REQUEST_SELECT_DATA })
          const token = getJwt()
          const headers = new Headers({
            'Authorization': `Bearer ${token}`
          })
          const retrieveSelectData = fetch('/api/SelectData/SelectData', {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json;charset=UTF-8'
            },
          })
            .then(handleErrors)
            .then(response => response.json())
            .then(selectData => {
              dispatch({ type: RECEIVE_SELECT_DATA, payload: selectData })
              saveSelectData(selectData)
            })
        }
      })
      .catch(error => {
        clearJwt()
        dispatch({ type: ERROR_LOGIN_TOKEN, payload: error.message })
      })
    addTask(task)
    return task
  }

Итак, теперь моя первая выборка заканчивается неопределенным обещанием, и оно просто прыгает вниз с неопределенным значением задачи,

Поверите ли вы, что вчера он работал отлично, а когда я попробовал его сегодня, он потерпел неудачу.

Почему этот блок кода приводит к сбою всего этого? Я комментирую его, и он работает нормально.

Я подозреваю, что это связано с двумя обещаниями и т. д., но должен быть правильный способ справиться с этим. Я бы подумал, что если бы он собирался сохранить токен JWT, это означало бы, что он завершен с первой загрузкой, однако что-то else неправильно... в этом блоке кода или, что более вероятно, в том, как он использовался.


person si2030    schedule 03.05.2017    source источник
comment
Вы имеете в виду, что обещание «задача» возвращает что-то в первом случае или возвращает неопределенное значение во втором (после обновления)? Я не уверен, что понимаю вашу проблему, но я подозреваю, что возвращение retrieveSelectData из соответствующей функции может быть решением.   -  person Igor Popov    schedule 03.05.2017
comment
Интересно, не могли бы вы расширить это, если бы могли .. @Igor   -  person si2030    schedule 03.05.2017
comment
Опять же, я не уверен, в чем проблема для вас, но, вообще говоря, если вы ожидаете, что где-либо, что requestLoginToken разрешается после разрешения retrieveSelectData, требуется цепочка от более позднего к предыдущему. То, как это реализовано, теперь обещает, что retrieveSelectData выполняется в манере, похожей на «выстрелил и забыл», и единственное, что заставляет вас знать о его завершении, - это действие RECEIVE_SELECT_DATA.   -  person Igor Popov    schedule 03.05.2017
comment
является ли confirmSelectDataExistance() асинхронной функцией? Если он возвращает обещание, вам нужно подождать, пока он вернет данные.   -  person Dat Tran    schedule 03.05.2017
comment
@Igor Я полагаю, что вы правы в этом ... у подтвержденияSelectDataExistance () нет обещания. он просто проверяет, есть ли что-то в localStorage. Как связать условный оператор и запустить его, если он верен?   -  person si2030    schedule 03.05.2017
comment
Если вы вернете обещание из функции, оно будет сцеплено. Интересно, возвращает ли submitSelectDataExistance обещание self. Если это так, вы можете вызвать его, например, confirmSelectDataExistance(). чем (trueOrFalse => {if (trueOrFalse) {fetch}})   -  person Igor Popov    schedule 03.05.2017
comment
Извините, но у меня проблемы с написанием этого синтаксиса. .then(confirmSelectDataExistance()) =› ??   -  person si2030    schedule 03.05.2017
comment
выложу как ответ   -  person Igor Popov    schedule 03.05.2017


Ответы (1)


Предполагая, что confirmSelectDataExistance является асинхронным и возвращает обещание, а обещание retrieveSelectData должно быть разрешено до requestLoginToken, решение может быть таким:

export const requestLoginToken = (username, password) =>
(dispatch, getState) => {
   dispatch({ type: REQUEST_LOGIN_TOKEN, payload: username })

   const payload = {
     userName: username,
     password: password,
   }

const task = fetch('/api/jwt', {
  method: 'POST',
  body: JSON.stringify(payload),
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
})
  .then(handleErrors)
  .then(response => response.json())
  .then(data => {
    dispatch({ type: RECEIVE_LOGIN_TOKEN, payload: data })
    saveJwt(data)
    //selectData download if nothing is local storage.

    return confirmSelectDataExistance().then(isConfirmed => {
      if (!isConfirmed) {
        dispatch({ type: REQUEST_SELECT_DATA })
        const token = getJwt()
        const headers = new Headers({
          'Authorization': `Bearer ${token}`
        })
        const retrieveSelectData = fetch('/api/SelectData/SelectData', {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json;charset=UTF-8'
          },
        })
        .then(handleErrors)
        .then(response => response.json())
        .then(selectData => {
          dispatch({ type: RECEIVE_SELECT_DATA, payload: selectData })
          saveSelectData(selectData)
        });

        return retrieveSelectData;
      }
    })
  })
  .catch(error => {
    clearJwt()
    dispatch({ type: ERROR_LOGIN_TOKEN, payload: error.message })
  })
addTask(task)
return task
}

Если saveSelectData также является асинхронным, вы должны вместо этого позвонить

 return saveSelectData(selectData);
person Igor Popov    schedule 03.05.2017