簡體   English   中英

redux-saga 中的 Promise

[英]Promises in redux-saga

我在這里找到了同樣的問題,但沒有我正在尋找的正確答案。

我正在開發一個帶有 CRUD 操作的簡單應用程序。 在編輯頁面上,在組件被掛載后( componentDidMount() ),應用程序會調度一個操作來檢索特定的帖子詳細信息:

dispatch({ type: FETCH_POST, id: 'post-id' })

我正在使用redux-saga並希望上述調用返回一個 Promise,以便我可以訪問 API 響應。

現在,沒有回調/承諾,我最終在商店中定義了一個新狀態(如post_edited )並將其連接/映射到組件中的道具以進行編輯頁面。

處理這種情況的最佳方法是什么?

您能否提供有關您的問題的更多信息? 我不確定我是否正確理解您的問題,但通常的做法是:

API.js

function apiCallToFetchPost(id) {
  return Promise.resolve({name: 'Test});
}

postSaga.js

function* fetchPostSaga({id}) {
  try {
    const request = yield call(apiCallToFetchPost, id);
    // -> in post reducer we will save the fetched data for showing them later 
    yield put({type: FETCH_POST_SUCCESS, payload: request}); 
  } catch (error) {
    yield put({type: FETCH_POST_SUCCESS_FAILURE, error})
  }
}

export function* onBootstrap() {
  yield takeLatest(FETCH_POST, fetchPostSaga);
}

有一個包完全符合 OP 的要求,即安排dispatch()可以返回承諾: @adobe/redux-saga-promise使用它,您可以通過以下方式定義“承諾操作”創建者:

import { createPromiseAction } from '@adobe/redux-saga-promise'

export const fetchPostAction = createPromiseAction('FETCH_POST')

“承諾操作”的dispatch()將返回一個承諾:

await dispatch(fetchPostAction({ id: 'post-id' }))

傳奇可能看起來像:

import { call, takeEvery }        from 'redux-saga/effects'
import { implementPromiseAction } from '@adobe/redux-saga-promise'

import { fetchPostAction } from './actions'

function * fetchPostSaga(action) {
  yield call(implementPromiseAction, action, function * () {
    const { id } = action.payload
    return yield call(apiCallToFetchPost, id)
  })
}

export function * rootSaga() {
  yield takeEvery(fetchPostAction, fetchPostSaga);
}

它將使用apiCallToFetchPost返回的值解決承諾,如果apiCallToFetchPost拋出錯誤,則拒絕。 它還使用您可以在減速器中訪問的解決方案/拒絕來分派次要操作。 該軟件包提供了您必須安裝才能使其工作的中間件

(免責聲明,我是作者)

我是@teroneko/redux-saga-promise的開發者。 它最初是從@adobe/redux-saga-promise派生出來的,但現在它已經完全改造為使用 @reduxjs/toolkit 中的 createAction 來支持 TypeScript。

為了與@ronen 的例子保持聯系,這里是 TypeScript 的等價物。

創建承諾操作(創建者):

import { promiseActionFactory } from '@teroneko/redux-saga-promise'
 
export const fetchPostAction = promiseActionFactory<void>().create<{ id: string }>('FETCH_POST')

發送承諾操作(來自創建者):

// promiseMiddleware is required and must be placed before sagaMiddleware!
const store = createStore(rootReducer, {}, compose(applyMiddleware(promiseMiddleware, sagaMiddleware)))
await store.dispatch(fetchPostAction({ id: 'post-id' }))

要解決/拒絕承諾操作(來自 saga):

import { call, takeEvery }        from 'redux-saga/effects'
import { implementPromiseAction } from '@teroneko/redux-saga-promise'

import { fetchPostAction } from './actions'

function * fetchPostSaga(action) {
  yield call(implementPromiseAction, action, function * () {
    const { id } = action.payload
    return yield call(apiCallToFetchPost, id)
  })
  // or for better TypeScript-support
  yield call(fetchPostAction.sagas.implement, action, function * () {
    const { id } = action.payload
    return yield call(apiCallToFetchPost, id)
  })
}

export function * rootSaga() {
  yield takeEvery(fetchPostAction, fetchPostSaga);
}

發生什么了?

  1. 承諾操作(創建者)被創建
  2. 承諾操作(來自創建者)被創建並
  3. 發送到商店。
  4. 然后 promise 操作被轉換為可等待的 promise 操作,其中將其延遲版本保存到元屬性中。 立即返回該操作並
  5. 傳遞給 saga 中間件。
  6. 現在可等待的承諾操作有資格在 implementPromiseAction 中使用,除了解決或拒絕保存在可等待承諾操作的元屬性中的延遲承諾之外,別無其他。

有關更多功能和高級用例,請參閱自述文件

另一種解決方案

onSubmit: (values) => {
  return new Promise((resolve, reject) => {
    dispatch(someActionCreator({ values, resolve, reject }))
  });
}

在傳奇中:

function* saga() {
  while (true) {
    const { payload: { values, resolve, reject } } = yield take(TYPE)
    // use resolve() or reject() here
  }
}

參考: https : //github.com/redux-saga/redux-saga/issues/161#issuecomment-191312502

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM