redux-saga原理的解读(代码示例)

如果下载的源码需要作者授权,请更换源码。本站免费分享资源不会增加授权

本篇文章给大家带来的内容是关于redux-saga原理的解读(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

笔者最近在做一些后台项目,使用的是Ant Design Pro,其使用了redux-saga处理异步数据流,本文将对redux-saga的原理做一个简单的解读,并将实现一个简易版的redux-saga。

Generator函数的自动流程控制

在redux-saga中,saga是指一些长时操作,用generator函数表示。generator函数的强大之处在于其可以手动的暂停、恢复执行,且可以与函数体外进行数据交互,看如下例子:

function *gen() {   const a = yield 'hello';   console.log(a); } cont g = gen(); g.next(); // { value: 'hello', done: false } setTimeout(() => g.next('hi'), 1000)  // 此时 a => 'hi'   一秒后打印‘hi'

可以看出来genrator函数何时进行下一步操作完全取决于外部的调度时机,且其内部执行状态也由外部的输入决定,这使得generator函数可以很方便的做异步流程控制。举个例子,我们首先读取一个文件的内容作为查询参数,然后请求一个查询接口并把返回的内容打印出来:

function getParams(file) {   return new Promise(resolve => {     fs.readFile(file, (err, data) => {       resolve(data)     })   }) } function getContent(params) {   //  request返回promise   return request(params) } function *gen() {   const params = yield getParams('config.json');   const content = yield getContent(params);   console.log(content); }

我们可以手动控制gen函数的执行:

const g = gen(); g.next().value.then(params => {   g.next(params).value.then(content => {     g.next(content);   }) })

以上可以达到我们的目的,但是过于繁琐,我们想要的是generator函数可以自动的执行,可以写一个简易的自动执行函数如下:

function genRun(gen) {   const g = gen();   next();   function next(err, pre) {     let temp;     (err === null) && (temp = g.next(pre));     (err !== null) && (temp = g.throw(pre));      if(!temp.done) {       nextWithYieldType(temp.value, next);     }   } } function nextWithYieldType(value, next) {   if(isPromise(value)) {     value       .then(success => next(null, success))       .catch(error => next(error))   }  } genRun(gen);

此时generator函数便可以自动执行,事实上我们可以发现,generator的内部状态完全是由nextWithYieldType决定的,我们可以根据yield的类型执行不同的处理逻辑。

Effect

事实上sagaMiddleware.run(saga)可以类似看做genRun(saga),而saga是由一个个的effect组成的,那么effect是什么?redux-saga官网的解释:一个 effect 就是一个 Plain Object JavaScript 对象,包含一些将被 saga middleware 执行的指令。redux-saga提供了很多Effect创建器,如call、put、take等,已call为例:

function saga*() {   const result = yield call(genPromise);   console.log(result); }

call(genPromise)生成的就是一个effect,它可能类似如下:

{   isEffect: true,   type: 'CALL',   fn: genPromise }

事实上effect只表明了意图,而实际的行为由类似于上文的nextWithYieldType完成,例如:

function nextWithYieldType(value, next) {   ...   if(isCallEffect(value)) {     value.fn(). then(success => next(null, success)).catch(error => next(error))     }  }

当genPromise函数返回的promise被resolve后便会打印出结果。

生产者与消费者

观察下面的例子

function *saga() {   yield take('TEST');   console.log('test...'); }  sagaMiddleware.run(test);

saga会在take(‘TEST’)处阻塞,只有执行了dispatch({type: ‘TEST’})后saga才能继续运行(注意:此时的dispatch方法是经过sagaMiddleware包装过的)。这给我们的感觉似乎很像是take是一个生产者,在等待disaptch的消费,事实上take只是一个Effect生成器,具体的处理逻辑依然是在nextWithYieldType完成的,类似于:

function nextWithYieldType(value, next) {   ...   // take('TEST')生成的effect简单的认为是  {isEffect: true, type: 'TAKE', name: 'TEST'}   if(isTakeEffect(value)) {     channel.take({pattern: value.name, cb: params => next(null, params)})     }  }

channel是一个任务生成器,它有两个方法:take生成任务,put消费任务:

function channel() {   /*     task = {       pattern,       cb     }   */   let _task = null;    function take(task) {     _task = task;   }    function put(pattern, args) {     if(!_task) return;     if(pattern == _task.pattern) _task.cb.call(null, args);   }    return {     take,     put   } }

显然任务是在执行dispatch的时候被消费掉的,这个工作是在sagaMiddleware中做的,类似于如下:

const sagaMiddleware = store => {   return next => action => {     next(action);          const { type, ...payload } = action;     channel.put(type, payload);   } }

看到这里我们可以发现,需要我们做的就是不断的完善nextWithYieldType这个函数,当完成了put、fork、takeEvery对应的逻辑后,一个具备基本功能的redux-saga就诞生啦,就不在赘述这些功能的实现了。

本文由(壳先生)整理自网络,如转载请注明出处:https://www.mrshell.com;
本站发布的内容若侵犯到您的权益,请邮件联系 i@mrshell.com 删除,我们将及时处理!
===========================================================================

1. 本站大部分下载资源收集于网络,不保证其完整性以及安全性,请下载后自行测试。
2. 本站资源仅供学习和交流使用,版权归资源原作者所有,请在下载后24小时之内自觉删除。
3. 不得使用于非法商业用途,商用请支持正版!不得违反国家法律,否则后果自负!
4. 若作商业用途,请购买正版,由于未及时购买和付费发生的侵权行为,与本站无关。
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!

=================================================================

壳先生 » redux-saga原理的解读(代码示例)

发表评论

提供最优质的资源集合

立即查看 了解详情