import { take, put, call, fork, select, takeEvery, all } from 'redux-saga/effects'
import * as actions from '../actions'
import { getCart } from '../reducers'
import { api } from '../services'
export function* getAllProducts() {
const products = yield call(api.getProducts)
yield put(actions.receiveProducts(products))
}
export function* checkout() {
try {
const cart = yield select(getCart)
yield call(api.buyProducts, cart)
yield put(actions.checkoutSuccess(cart))
} catch (error) {
yield put(actions.checkoutFailure(error))
}
}
export function* watchGetProducts() {
/*
takeEvery will fork a new `getAllProducts` task on each GET_ALL_PRODUCTS actions
i.e. concurrent GET_ALL_PRODUCTS actions are allowed
*/
yield takeEvery(actions.GET_ALL_PRODUCTS, getAllProducts)
}
export function* watchCheckout() {
while (true) {
yield take(actions.CHECKOUT_REQUEST)
/*
***THIS IS A BLOCKING CALL***
It means that watchCheckout will ignore any CHECKOUT_REQUEST event until
the current checkout completes, either by success or by Error.
i.e. concurrent CHECKOUT_REQUEST are not allowed
TODO: This needs to be enforced by the UI (disable checkout button)
*/
yield call(checkout)
}
}
export default function* root() {
yield all([fork(getAllProducts), fork(watchGetProducts), fork(watchCheckout)])
}
对于这个问题,其实免不了比较一下redux-thunk和redux-saga。
不管是thunk还是saga,都是redux的一个中间件。至于为什么要使用中间件,在redux中,reducer都是纯函数,由于是纯函数,所以操作的返回结果都是依赖于它的参数,执行过程不会产生副作用(即传什么,返回什么)。但是在实际的开发过程中,我们需要处理一些异步操作,Redux的作者将这些副作用的操作以中间件的形式提供给开发者,开发者可以自行选择或自己实现。
Redux-thunk
下面是thunk的实现:
由源码可以看出,其实thunk仅仅只是对传入的函数进行了执行操作,并不关心函数的主体内容。比如我们可以传入一个如下的异步操作来触发action:
由于函数的实现比较复杂,同时函数的实现方法不固定,如果异步请求每次都需要定义一个action显然开发成本是很高的。所以thunk的缺点总结一下就是:
Redux-saga
redux-saga是通过ES6中的generator实现的(babel的基础版本不包含generator语法,因此需要在使用saga的地方import ‘babel-polyfill’)。redux-saga本质是一个可以自执行的generator。
先来看一下saga官方提供的例子shoppingCat中saga/index.js文件。
着重看一下getAllProducts()这个异步操作方法,找到getAllProducts()对应的actions代码如下:
上面的代码action与我们redux中同步action的key是统一的。
redux-saga中的effect本质是一个特定的函数,返回纯文本对象。即通过effect返回的一个字符串,saga-middleware根据这个字符串来执行真正的异步操作,具体表现成如下形式(来自异步方案选型redux-saga 和 redux-thunk(async/await)):
异步操作-->Effect函数-->纯文本对象-->saga-middleware-->执行异步操作
总结一下saga的优点:
总结
对比之下,redux-saga的优点还是很多的,如果排除学习成本的因素,更推荐使用redux-saga作为中间件进行状态管理。
以上都是个人通过各大博客的学习总结,仅用于个人学习,肯定有很多不对或理解不好的地方,希望能够帮我指正,感谢。。。