gpt4 book ai didi

reactjs - Saga 中的“yield all”并不等待所有效果完成

转载 作者:行者123 更新时间:2023-12-03 13:41:00 25 4
gpt4 key购买 nike

我有一个像这样的传奇(一些伪代码)。

Saga1 调用 API。根据结果​​,我需要调用另外两个 API。如果所有 API 均成功,我将调用 onSuccess,否则调用 onFailure。

该代码似乎几乎可以正常工作,但并非完全如此。我在使用 yield all 时面临的问题是,一旦调用第一个yield put,它就认为 saga2 和 saga3 已完成(请参阅 saga2/3 中的注释)。它没有等待获取 yield 完成。

我认为这部分是由于我对“完整效果”含义的误解。但除此之外,我希望让出所有的东西等到一切都完成。我希望 saga2/3 中的 fetch 抛出的任何异常都能被 saga1 中的 catch 捕获。

saga1(action) {

const { onSuccess, onFailure } = action.payload;

try {
yield fetch...

if(response.some_condition) yield all([
put(saga2()),
put(saga3())
])

onSuccess();

}
catch(e) {
onFailure();
}
}

saga2(action) {

yield put(someaction()) // This yields
yield fetch...
}

saga3(action) {

yield put(someaction()) // This yield
yield fetch...
}

下面的代码与我下面关于 catch 不起作用的评论相关

action1 () { // action2 is same
try {
yield fetch();
yield put(FINISHED_1);
}
catch(e) {
throw (e);
}
}

saga1() {
try {
yield put(action1());
yield put(action2());

yield all([
take(FINISHED_1),
take(FINISHED_2),
])
console.log("this doesn't print if exception in either action");
}
catch(e) {
console.log("this doesn't print if exception in either action");
}
finally {
console.log("this prints fine");
}
}

最佳答案

1) 等待多个call效果运行完成:

yield all([
call(saga2, arg1, arg2, ...),
call(saga3, arg1, arg2, ...)
]);

2) 分派(dispatch)多个操作并等待其成功操作被分派(dispatch):

yield put(action1());
yield put(action2());

yield all([
take(ACTION_1_SUCCESS),
take(ACTION_2_SUCCESS)
]);

回复评论的编辑

如果您直接使用all(上面#1)调用传奇,那么您可以按照常规捕获错误

try {
yield all([
call(saga2, arg1, arg2, ...),
call(saga3, arg1, arg2, ...)
]);
} catch (e) {
// ...
}

但是,如果一个 saga put 的操作被其他 sagas 监听,则该 saga 不会收到这些异常。 Saga1 不是这些传奇的父级或附属于这些传奇。它只是调度操作,其他地方的一些其他任务则监听并响应。

为了让 Saga1 了解这些 sagas 中的错误,saga 不应抛出错误,而应分派(dispatch)带有错误负载的操作:

function* saga2(action) {
try {
const result = yield call(...);
yield put(action2Success(result));
} catch (e) {
yield put(action2Failure(e.message));
}
}

触发 saga2(通过 put(action2()))的 saga 可以处理成功和失败:

function* saga1(action) {
yield put(action2());
yield put(action3());

const [success, failure] = yield race([
// if this occurs first, the race will exit, and success will be truthy
all([
take(ACTION_2_SUCCESS),
take(ACTION_3_SUCCESS)
]),

// if either of these occurs first, the race will exit, and failure will be truthy
take(ACTION_2_FAILURE),
take(ACTION_3_FAILURE)
]);

if (failure) {
return;
}

// ...
}

Sagas 应该处理异常并使用错误状态更新存储,而不是抛出错误。使用 saga 并发构造时,在 sagas 中抛出错误会变得困惑。例如,您无法直接捕获 fork 任务引发的错误。此外,使用操作来表示 saga 结果可以在您的存储中保留良好的事件日志,其他 saga/reducer 可以对其做出响应。当您调用其他saga时,应该启动该saga的操作(例如takeEvery(THE_ACTION, ...))不会被调度。

关于reactjs - Saga 中的“yield all”并不等待所有效果完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53071610/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com