前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redux-sage笔记

redux-sage笔记

作者头像
flytam
发布2020-01-14 16:54:17
6950
发布2020-01-14 16:54:17
举报

前言:以前用redux处理异步状态都使用redux-thunk那个库。也一直听说redux-saga是个和redux-thunk能够实现类似功能的库,而且redux-saga的处理方法更加高压和方便。这几天阅读了下文档写些小结。

saga是用来分发action进行处理,使系统流程更加清晰。推荐使用Generator函数。

以下是一些saga的常用方法

redux/saga
  • takeEvery
    • yield* takeEvery('PRODUCTS_REQUESTED', fetchProducts)
    • 每当有PRODUCTS_REQUESTED的action分发的时候就执行fetchProducts函数,在这里fetchProducts函数也是Generator函数(tips:注意yield* 就是在Generator内执行另一个Generator函数)
    • takeEvery('\*', function * xx(){/\** ***/})表示匹配所有的action
  • takeLatest
    • 只执行最新的任务,之前如果有正在执行的任务则会被取消
redux-saga/effects

tips: effects纯文本Javascript对象 - call - call() 调用给定函数。注意的是,如果call调用fetch,在默认的fetch状态下返回的是Promise实例,但是由于是call调用,返回的是文本信息,可以直接调用 - put - put({type: 'INCREMENT'}) 发起一个action到store - take 第二个参数表示对应匹配的action所要执行的函数。第一个参数如果是数组的话,表示可以并发监听action - 可以更好的控制状态流 - 如下一个函数控制登陆和登出

代码语言:javascript
复制
//一个简单的登陆逻辑实现
//这个是会被阻塞的
     function* loginFlow() {
      while(true) {
        const = {} = yield take('LOGIN')//左侧可以获取到这个action的一些信息
        // ... perform the login logic
        yield take('LOGOUT')
        // ... perform the logout logic
      }
    }

import { take, call, put } from 'redux-saga/effects'
import Api from '...'

function* authorize(user, password) {
  try {
    const token = yield call(Api.authorize, user, password)
    yield put({type: 'LOGIN_SUCCESS', token})
    return token
  } catch(error) {
    yield put({type: 'LOGIN_ERROR', error})
  }
}

function* loginFlow() {
  while(true) {
    const {user, password} = yield take('LOGIN_REQUEST')
    const token = yield call(authorize, user, password)
    if(token) {
      yield call(Api.storeItem({token}))
      yield take('LOGOUT')
      yield call(Api.clearItem('token'))
    }
  }
}
  • fork
    • fork不阻塞后续的yield
  • cancel
    • 取消fork事务
代码语言:javascript
复制
function* authorize(user, password) {
  try {
    const token = yield call(Api.authorize, user, password)
    yield put({type: 'LOGIN_SUCCESS', token})
    return token
  } catch(error) {
    if(!isCancelError(error))
      yield put({type: 'LOGIN_ERROR', error})
  }

function* loginFlow() {
  while(true) {
    const {user, password} = yield take('LOGIN_REQUEST');//监听登录请求
    const task = yield fork(authorize, user, password)//收到登陆请求后,发起认真。因为是fork所以是不阻塞下面的take['LOGOUT','LOGIN_ERROR']的
    const action = yield take(['LOGOUT', 'LOGIN_ERROR'])
    if(action.type === 'LOGOUT')
      yield cancel(task) //取消之前的fork事务。因为可能登录请求未成功我们就发起了登出的事件。取消fork事务的时候,会在authorize内抛出一个错误
    yield call(Api.clearItem('token'))//清空本地的token
  }
}
  • race
    • 用法:race({fun1,fun2}),某个fun执行完这个race就结束了
    • 除了第一个被race的Generator函数外,其它的Generator函数会结束并抛出异常
代码语言:javascript
复制
function* backgroundTask() {
  while(true) { ... }
}

function* watchStartBackgroundTask() {
  while(true) {
    yield take('START_BACKGROUND_TASK')
    yield race({
      task: call(backgroundTask),
      cancel: take('CANCEL_TASK')//例如接受到CANCEL_TASK 的action的时候,backgroundTask函数内就会抛出异常
    })
  }
}
其它
  • yield [fun1,fun2] 并发执行fun1、fun2 相当于Promise.all 的功能,所有的fun都结束了才会结束这个yield
  • 被强行cancel的会抛出SagaCancellationException(在redux-sage下) 错误。未被捕获的话,这个错误是不会向上冒泡的

使用redux-saga来处理一些复杂的流程的时候似乎比较不错

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • saga是用来分发action进行处理,使系统流程更加清晰。推荐使用Generator函数。
  • 以下是一些saga的常用方法
    • redux/saga
      • redux-saga/effects
        • 其它
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档