• redux-Saga


    概念

    image

    redux-saga是redux的中间件,中间件的作用是为redux提供额外的功能,用来处理异步产生的副作用
    
    sages使用generator来yield Effects
    effects API 如 fork,call,take,put,cancel 等来创建 Effect。
    

    redux-saga

    //拿到createSagaMiddleware中间件
    import createSagaMiddleware from "redux-saga";
    
    //创建中间件
    const sagaMiddleware = createSagaMiddleware()
    
    //将中间件注入store
    const store = createStore(reducer, applyMiddleware(sagaMiddleware))
    
    //启动中间间,将rootSaga配置放入中间件
    sagaMiddleware.run(rootSaga)
    

    saga配置

    //redux-saga/effects拿到处理异步dispatch的方法
    import { put, takeEvery, delay } from "redux-saga/effects";
    
    //模拟异步请求,action的时候执行
    export function* incrementAsync() {
        //延时
      yield delay(1000);
      //派发action
      yield put({ type: "INCREMENT" });
    }
    //中间件启动的时候执行
    export default function* rootSaga() {
      //并行执行异步请求
      yield takeEvery("INCREMENT_ASYNC", incrementAsync);
    }
    
    //模拟执行过程
    <Counter
      value={store.getState()}
      onIncrement={() => action('INCREMENT')}
      onDecrement={() => action('DECREMENT')}
      onIncrementIfOdd={() => action('INCREMENT_IF_ODD')}
      onIncrementAsync={() => action('INCREMENT_ASYNC')}
    />,
    
    
    //takeLatest
    export function* incrementAsync() {
      yield delay(500);
      yield put({ type: "INCREMENT" });//只派发最新的一次action
    }
    
    export default function* rootSaga() {
      //只执行最新的action
      yield takeLatest("INCREMENT_ASYNC", incrementAsync);
    }
    

    redux-saga分类

    worker saga做调用api,的异步操作
    watcher saga监听被dispatch的actions,收到actions消息后通知worker执行任务
    root saga 立即启动saga的唯一入口
    

    Effect概念

    一个 Saga 所做的实际上是组合那些所有的 Effect,共同实现所需的控制流。 最简单的例子是直接把 yield 一个接一个地放置来对序列化 yield Effect。你也可以使用熟悉的控制流操作符(if, while, for) 来实现更复杂的控制流。
    

    错误处理,try & catch

    //用try,catch来捕获异步执行中的错误
    function* fetchProducts() {
      try {
        const products = yield call(Api.fetch, '/products')
        yield put({ type: 'PRODUCTS_RECEIVED', products })
      }
      catch(error) {
        yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
      }
    }
    

    dispatch action,put

    //用put来派发异步请求结果action
    import { call, put } from 'redux-saga/effects'
    //...
    
    function* fetchProducts() {
      const products = yield call(Api.fetch, '/products')
      // 创建并 yield 一个 dispatch Effect
      yield put({ type: 'PRODUCTS_RECEIVED', products })
    }
    

    声明式Effects,call

    //用call来代替普通的异步请求
    import { call } from 'redux-saga/effects'
    import Api from '...'
    
    const iterator = fetchProducts()
    
    // expects a call instruction
    assert.deepEqual(
      iterator.next().value,
      call(Api.fetch, '/products'),
      "fetchProducts should yield an Effect call(Api.fetch, './products')"
    )
    

    Saga Helpers,takeLates * takeEvery

    import { takeLatest } from 'redux-saga'
    
    function* watchFetchData() {
      yield* takeLatest('FETCH_REQUESTED', fetchData)
    }
    
    import { takeEvery } from 'redux-saga/effects'
    
    // FETCH_USERS
    function* fetchUsers(action) { ... }
    
    // CREATE_USER
    function* createUser(action) { ... }
    
    // 同时使用它们
    export default function* rootSaga() {
      yield takeEvery('FETCH_USERS', fetchUsers)
      yield takeEvery('CREATE_USER', createUser)
    }
    

    监听未来的action,take

    //使用take监听特定的action
    import { take, put } from 'redux-saga/effects'
    
    function* watchFirstThreeTodosCreation() {
      for (let i = 0; i < 3; i++) {
        const action = yield take('TODO_CREATED')
      }
      yield put({type: 'SHOW_CONGRATULATION'})
    }
    

    无阻塞调用fork

    function* loginFlow() {
      while(true) {
        const {user, password} = yield take('LOGIN_REQUEST')
        // fork return a Task object
        const task = yield fork(authorize, user, password)
        const action = yield take(['LOGOUT', 'LOGIN_ERROR'])
        if(action.type === 'LOGOUT')
          yield cancel(task)
        yield call(Api.clearItem('token'))
      }
    }
    
    

    同时执行多个任务

    
    const [users, repos] = yield [
      call(fetch, '/users'),
      call(fetch, '/repos')
    ]
    

    竞赛race

    
    function* fetchPostsWithTimeout() {
      const {posts, timeout} = yield race({
        posts: call(fetchApi, '/posts'),
        timeout: call(delay, 1000)
      })
    
      if (posts)
        put({type: 'POSTS_RECEIVED', posts})
      else
        put({type: 'TIMEOUT_ERROR'})
    }
    
  • 相关阅读:
    zookeeper 是如何保证事务的顺序一致性的?
    Hibernate的一级缓存和二级缓存有什么区别?
    写出Hibernate中核心接口/类的名称,并描述他们各自的责任?
    请说说你对Struts2的拦截器的理解?
    什么是MVC模式?   
    JDBC中的Statement 和PreparedStatement的区别?
    说说数据库连接池工作原理和实现方案?
    如何删除表中的重复数据,只保留一条记录?
    Where和having都是条件筛选关键字,它们有什么分别?
    JSP和Servlet有哪些相同点和不同点?
  • 原文地址:https://www.cnblogs.com/pluslius/p/10570137.html
Copyright © 2020-2023  润新知