背景
在saga方法里,我执行了一个方法,该方法返回了一个promise;现在,我需要去捕捉promise的错误,然后执行一个generator函数,也就是:
function* generator(){
...
}
const p = getPromise();
p.catch((e) => {
generator()
})
问题
一般来说,在saga里执行函数,通常都是yield call(func);但现在catch里,不允许出现yield关键字!所以我又想了下,generator函数的一般执行方法,如下
demo
function* gen() {
console.log('执行gen');
yield 1;
}
// effect.js
function *test(){
console.log('yield + call:');
yield call(gen);
console.log('yield:');
yield gen();
console.log('call:');
call(gen);
console.log('generator的next:');
gen().next();
}
执行test方法,输出如下
yield + call:
执行gen
yield:
执行gen
call:
generator的next:
执行gen
可以看到,直接call一个generator是没用的
解决
那么现在怎么办呢?
最后我这边是通过sagaMiddleware方法解决的;官方说法如下:
middleware.run(saga, ...args)
Dynamically run saga. Can be used to run Sagas only after the applyMiddleware phase.
saga: Function: a Generator functionargs: Array<any>: arguments to be provided tosaga
Notes
saga must be a function which returns a Generator Object. The middleware will then iterate over the Generator and execute all yielded Effects.
saga may also start other sagas using the various Effects provided by the library. The iteration process described below is also applied to all child sagas
If the execution results in an error (as specified by each Effect creator) then the throw(error) method of the Generator is called instead. If the Generator function defines a try/catch surrounding the current yield instruction, then the catch block will be invoked by the underlying Generator runtime. The runtime will also invoke any corresponding finally block.
In the case a Saga is cancelled (either manually or using the provided Effects), the middleware will invoke return() method of the Generator. This will cause the Generator to skip directly to the finally block.
代码
// index.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import sagas from './sagas';
export const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const enhancer = composeEnhancers(
applyMiddleware(...middlewares),
// other store enhancers if any
);
export const store = createStore(countReducer, modals, enhancer);
sagaMiddleware.run(sagas);
function* gen(){
...
}
const p = getPromise();
p.catch((e) => {
sagaMiddleware.run(gen);
})