我试图以以下方式将多个操作链接在一起:
A.将用户数据张贴到数据库
B.使用已发布的数据查询结果的弹性搜索
(我并行做A和B)
B1。使用ES的结果,查询原始数据库以获得两个表B2的结果。导航到新页面并更新UI
我现在正在使用块来对我的代码进行推理,但我也发现这个异步模式非常冗长:
export function fetchRecipes(request) {
return function(dispatch) {
dispatch(requestRecipes(request))
return fetch(url)
.then(response => response.json())
.then(json => dispatch(receiveRecipes(request, json))
)
}
}这与"requestRecipes“和"receiveRecipes”作为其他动作创建者一样,似乎只是为了进行一个异步调用。(请求、接收和获取函数)
摘要:当您将输出相互依赖的2-3异步操作链接起来时(我需要在可能的情况下对其进行promisify ),是否有一种更有效的方法来这样做,而不为每个异步调用编写3个函数?
我想一定有办法的。我与Redux文档进行模式匹配,很快就被我正在创建的函数所淹没
非常感谢你的反馈!
发布于 2016-04-18 06:44:36
您可以使用redux-saga而不是redux-thunk来更容易地实现这一点。redux-saga允许您使用生成器来描述您的工作,并且更容易进行推理。
第一步是描述如何将数据传递给redux,而不必担心服务或异步。
Actions
// actions.js
function createRequestTypes(base) {
return {
REQUEST: base + "_REQUEST",
SUCCESS: base + "_SUCCESS",
FAILURE: base + "_FAILURE",
}
}
// Create lifecycle types on `RECIPES`
export const RECIPES = createRequestTypes("RECIPES")
// Create related actions
export const recipes = {
// Notify the intent to fetch recipes
request: request => ({type: RECIPES.REQUEST, request})
// Send the response
success: response => ({type: RECIPES.SUCCESS, response})
// Send the error
error: error => ({type: RECIPES.FAILURE, error})
}减速器
// reducer.js
import * as actions from "./actions"
// This reducer handles all recipes
export default (state = [], action) => {
switch (action.type) {
case actions.RECIPES.SUCCESS:
// Replace current state
return [...action.response]
case actions.RECIPES.FAILURE:
// Clear state on error
return []
default:
return state
}
}服务
我们还需要菜谱API。在使用redux-saga时,声明服务的最简单方法是创建一个(纯)函数,该函数将请求作为参数读取并返回一个Promise。
// api.js
const url = "https://YOUR_ENPOINT";
export function fetchRecipes(request) {
return fetch(url).then(response => response.json())
}现在我们需要连线行动和服务。这就是redux-saga发挥作用的地方。
// saga.js
import {call, fork, put, take} from "redux-saga/effects"
import * as actions from "./actions"
import * as api from "./api"
function* watchFetchRecipes() {
while (true) {
// Wait for `RECIPES.REQUEST` actions and extract the `request` payload
const {request} = yield take(actions.RECIPES.REQUEST)
try {
// Fetch the recipes
const recipes = yield call(api.fetchRecipes(request))
// Send a new action to notify the UI
yield put(actions.fetchRecipes.success(recipes))
} catch (e) {
// Notify the UI that something went wrong
yield put(actions.fetchRecipes.error(e))
}
}
}
function* rootSaga() {
yield [
fork(watchFetchRecipes)
]
}就这样!每当组件发送RECIPES.REQUEST操作时,saga都会连接并处理异步工作流。
dispatch(recipes.request(req))redux-saga最棒的地方在于,您可以轻松地在工作流期间链接异步效果和分派操作。
发布于 2016-04-18 07:28:57
根据您的描述,只有在所有这些异步操作(B1)结束时才能真正更新UI。
如果您不使用前面异步调用的结果来更改应用程序状态/更新UI,那么拥有这些细粒度操作有什么好处?
当然,有“加载/请求启动”和“已完成的加载/请求停止”之类的事情,但在我看来,在您的示例中,您只需要在redux之外执行链接的异步调用(在某种API层中),并且只使用一个操作。此操作发出一个"REQUEST_STARTED",然后调用API层,后者执行DB调用和elasticsearch请求等,然后根据承诺的结果分派"REQUEST_SUCCESS“或"REQUEST_FAILURE",这将为您提供更新UI所需的数据。
这样,redux中的状态只关注一个副作用,而不是链式调用的实现细节。而且,您的操作变得简单得多,因为它只处理一个异步调用的结果。
https://stackoverflow.com/questions/36682138
复制相似问题