别人的传奇

A saga for others sagas

我发现在 redux-saga 中组织代码有困难。我有一个特殊的 saga 可以发出 http 请求(以及许多其他工作)。

我不希望它成为命令式函数,但我也不想太混乱。

目前我已经创建了一个将被此操作调用的传奇:

export const makeServerRequest = (options, success, error) => ({type: MAKE_REQUEST, options, success, error});

传奇是这样的:

function *makeRequestSaga(action) {
    try {
        // saga magic
        yield put(action.success(response));
    } catch (error) {
        yield put(action.error(error));
    }
}

function *serverSagasWatcher() {
    yield takeEvery(MAKE_REQUEST, makeRequestSaga);
}

我发现这种方法的问题很难遵循逻辑,在我看来又回到了回调时间。

该动作被其他 sagas 以这种方式调用:

yield put(makeServerRequest(options, loginSuccessful, loginError));

function *loginSuccessfulSaga(action) {
    console.log('Success');
}

function *loginErrorSaga(action) {
    console.log('Login error');
}

通过这种方式,我有更多的观察者(每个执行请求的传奇都需要定义两个动作和 运行 两个观察者,每个 return 函数一个)。

此用例的最佳做法是什么?

我也可以做真正的回调,但问题是生成器将保持活动状态直到回调结束,所以如果回调中存在无限循环,那么生成器将永远挂起。

如果我需要执行命令式请求,那么 redux-sagaredux-thunk 有什么优势?

我确定我遗漏了一些非常简单的东西,但我没有找到任何解决方案...

很可能,您通常不需要这样的构造。相反,你在单元TRY/catch中的生成器中执行一个函数中的一系列操作,并且通过yield + Promise.

的构造来实现异步和等待。

也许您的意思是以下解决方案?

function makeServerRequest(options) {
    return fetch(options) /* Or more complex fetch logic */
        .then((result) => {
            let isOkay = true, errorMessage = null
            /* Implement your verification logic here */
            return isOkay
                ? Promise.resolve(result)
                : Promise.reject(errorMessage)
        })
}

function * makeRequestSaga(action) {
    try {
        yield call(makeServerRequest(options));
        yield put(action.success(response));
    } catch (error) {
        yield put(action.error(error));
    }
}