[英]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);
}
發生什么了?
有關更多功能和高級用例,請參閱自述文件。
另一種解決方案
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.