Posts Redux/React-Redux/Redux-Saga
Post
Cancel

Redux/React-Redux/Redux-Saga

Redux

enter description here

React-Redux

1
2
3
4
5
6
7
8
<Provider store = {store}>
 <App />
<Provider>
// 让所有组件都能够访问到Redux中的数据

connect
mapStateToProps
mapDispatchToProps

Redux-Saga: 创建saga middleware 并且将其连接至redux store

1
2
3
4
const store = createStore(
  reducer,
  applyMiddleware(createSagaMiddleware(helloSaga)) // 使用 applyMiddleware 将 middleware 连接至 Store
)

Sagas 被实现为 Generator functions,它会 yield 对象到 redux-saga middleware。 被 yield 的对象都是一类指令,指令可被 middleware 解释执行。当 middleware 取得一个 yield 后的 Promise,middleware 会暂停 Saga,直到 Promise 完成。

1
2
3
4
5
作用:决定什么时候发起dispatch

解决在reducer纯函数不能处理异步方法,需要中间件处理
组件中发生的action后,在进入reducer之前需要完成一个异步任务,
比如发送ajax请求后拿到数据后,再进入reducer,显然原生的redux是不支持这种操作的
  • put 阻塞的effect, 可以看作是redux的dispatch函数, 发送action的effect, 每个put(action)就相当dispatch(action)出去,reducer边接收到相应的action.type就会对数据进行相应的操作,最后通过react-redux的connect回到视图中,完成了一次数据驱动视图,

  • call 阻塞的effect,类似于async的await,只有当前任务成功才往下继续执行

  • take 阻塞的effect, 主要用来监听action.type的,只有监听到了,才会继续往下执行

  • takeEvery takeEvery就像一个流水线的洗碗工,过来一个脏盘子就直接执行后面的洗碗函数,一旦你请了这个洗碗工他会一直执行这个工作,不会停止接盘子的监听过程和触发洗盘子函数 这个洗碗工可以无限次的接受脏盘子的action,也不会停止洗盘子,所以你没办法指定让他具体洗盘子 区别: 监听一个action, 只要action被触发就执行

  • takeLatest takeLatest是在他的程序没运行完时,再次运行时,会取消它的上一个任务;而takeEvery则是运行都会fork一个新的任务出来,不会取消上一个任务;所以,用takeLatest来处理重复点击的问题
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    const takeLatest = (patternOrChannel, saga, ...args) => fork(function*() { 
      let lastTask
      while (true) { 
           const action = yield take(patternOrChannel) 
           if (lastTask) { 
               yield cancel(lastTask) // cancel is no-op if the task has already terminated 
           }
           lastTask = yield fork(saga, ...args.concat(action)) 
      } 
    })
    
  • fork 非阻塞的effect, 与call相似,都是用来调用其他函数,

    返回一个任务,这个任务是可以被取消的, call返回的就是它执行的正常返回结果

  • cancel 取消任务,配合fork适合 ```bash const task = yield fork(getData, action); yield take(“CANCEL_REQUEST”); yield cancel(task);

*getData(action) { try(){} catch(){} finally(){ yield cancelled() } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#### fork & spawn

```markdown
const { delay, runSaga } = require("redux-saga");
const fetch = require("node-fetch");
const { fork, spawn, call, put} = require("redux-saga/effects");


function* fetchResource(resource) {
    console.log(`Fetch ${resource} start`);
    const response = yield call(fetch, "https://jsonplaceholder.typicode.com" + resource);
    const text = yield call(response.text.bind(response));
    console.log(`Fetch ${resource} end`);
}

function* fetchAll() {
    console.log("Fork or Spawn start");
    // this is pseudo code, I mean here that you can use either
    // fork or spawn, check results below
    const task1 = yield fork||spawn(fetchResource, "/posts/1"); 
    const task2 = yield fork||spawn(fetchResource, "/posts/2");
    console.log("Fork or Spawn end");
}

function* main() {
    console.log("Main start");
    yield call(fetchAll);
    console.log("Main end");
}

runSaga({}, main);

// RESULTS WITH FORK():   |  RESULTS WITH SPAWN():
//                        |
// Main start             |  Main start
// Fork start             |  Spawn start
// Fetch /posts/1 start   |  Fetch /posts/1 start
// Fetch /posts/2 start   |  Fetch /posts/2 start
// Fork end               |  Spawn end
// Fetch /posts/2 end     |  Main end <-- 
// Fetch /posts/1 end     |  Fetch /posts/2 end
// Main end <--           |  Fetch /posts/1 end
This post is licensed under CC BY 4.0 by the author.