Friday, January 22, 2021
Lưu Xuân Trường's Blog
  • Trang chủ
  • Backend
    • Laravel
    • Golang
    • NodeJS
    • MongoDB
    • Redis
    • WordPress
      • Kinh nghiệm
      • Plugins
  • Frontend
    • CSS
    • Javascript
      • ReactJS
      • UmiJS
      • VueJS
      • NuxtJS
      • Angular
      • RxJS
    • Game HTML5
  • Mobile
    • React Native
    • IOS
    • Android
    • Flutter
  • Tutorials
    • Redux-Saga
  • How to
  • Góc Ngoài Lề
    • Sống Chậm Nghĩ Sâu
    • Câu Hỏi Phỏng Vấn
    • IQ Test
  • Liên Hệ
No Result
View All Result
  • Trang chủ
  • Backend
    • Laravel
    • Golang
    • NodeJS
    • MongoDB
    • Redis
    • WordPress
      • Kinh nghiệm
      • Plugins
  • Frontend
    • CSS
    • Javascript
      • ReactJS
      • UmiJS
      • VueJS
      • NuxtJS
      • Angular
      • RxJS
    • Game HTML5
  • Mobile
    • React Native
    • IOS
    • Android
    • Flutter
  • Tutorials
    • Redux-Saga
  • How to
  • Góc Ngoài Lề
    • Sống Chậm Nghĩ Sâu
    • Câu Hỏi Phỏng Vấn
    • IQ Test
  • Liên Hệ
No Result
View All Result
Lưu Xuân Trường's Blog
No Result
View All Result

Quản lý trạng thái tải khi dùng redux-saga

truongluu by truongluu
01/11/2020
in Javascript, ReactJS
Reading Time: 5min read
0 0
1
Quản lý trạng thái tải khi dùng redux-saga
0
SHARES
99
VIEWS
Share on FacebookShare on Twitter

Bài viết trước mình đã giới thiệu về package redux-waiters (quản lý trạng thái tải của action khi dùng redux-thunk). Vậy đối với các ứng dụng web các bạn dùng redux-saga thì sao nhỉ. Bài này mình không đề cập tới redux-saga là gì nhé, các bạn xem thêm ở official document

Đối với các ứng dụng cũ, các bạn đã dùng redux-thunk, thì cũng không có vấn đề gì, với những tính năng mới thì các bạn cũng có thể chuyển qua sử dụng redux-saga, chạy song song với redux-thunk.

Để quản lý được trạng thái tải của redux-saga, thì mình có cập nhật lại package redux-waiters, thì từ phiên bản 1.0.6, redux-waiters sẽ hổ trợ vừa redux-thunk và redux-saga. Và đây là cách mình giải quyết vấn đề, gồm có 2 bước sau

  • Xử lý lại saga worker, để cập nhật được trạng thái bắt đầu của 1 action
  • Cập nhật thêm waiter middleware để xử lý thêm trường hợp callback là Generator function

Xử lý lại saga worker

xét đoạn mã khi làm việc với redux-saga, trong file saga.js

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
import { all, takeEvery, delay, put } from 'redux-saga/effects'
 
import { increAction } from './reducers/counter'
 
function* incrCounter(action) {
  try {
 
    console.log('call incrCounter start', action)
    yield delay(4000)
    console.log('call increcounter continue')
    yield put(increAction.success(1));
    console.log('call incr success')
  } catch (err) {
    console.log('err', err)
  }
}
 
function* watchIncrCounter() {
  yield takeEvery(increAction.start,incrCounter)
}
 
function* watchLog() {
  yield takeEvery('*', function* log(action) {
    console.log('action', action)
  })
}
 
 
export default function* rootSaga() {
  yield all([
    watchIncrCounter(),
    watchLog()
  ])
}

Với đoạn mã trên thì mình có 2 saga watcher

  1. watchIncrCounter: theo dõi tăng giá trị counter
  2. watchLog: log lại các action được gọi (sử dụng pattern *)

Cách xử lý của mình ở đây là thay vì saga watcher sẽ call tới 1 saga worker là 1 generator function, thì mình sẽ wrap cái saga worker lại, để trước khi nó call tới 1 saga worker để sử lý các effect liên quan thì mình phải cập nhật được trạng thái tải của action trước tiên :). Các bạn theo dõi đoạn mã bên dưới mình đã xử lý lại

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function wrapWithGenerator(handler) {
  return function* wr(action) {
    if (!!action.continue) {
      yield* handler(action)
    } else {
      yield put({
        type: increAction.start,
        callback: handler,
        action
      })
    }
 
  }
}
 
function* watchIncrCounter() {
  yield takeEvery(increAction.start, wrapWithGenerator(incrCounter))
}

Để thực hiện điều này, đầu tiên mình wrap cái saga worker lại với hàm wrapWithGenerator. Bước tiếp theo mình xử lý mình cũng sẽ trả về đúng đối tượng là takeEvery sẽ call là 1 generator function mới là function* wr(action){}. Tiếp theo với đoạn mã:

1
2
3
4
5
6
7
8
9
if (!!action.continue) {
      yield* handler(action)
    } else {
      yield put({
        type: increAction.start,
        callback: handler,
        action
      })
    }

Mục đích của đoạn mã này là thay vì call tới saga worker liền mình sẽ put 1 action lên middleware để update lại trạng thái bắt đầu của sự kiện (xem thêm ở phần cập nhận waiter middleware), sau đó từ middleware mình sẽ recall lại action với 1 thuộc tính mới là continue= true, để cho biết là call trực tiếp với saga worker để xử lý

Cập nhật waiter middleware

Xem đoạn mã waiter middleware mình đã cập nhật để xử lý thêm vụ callback là generator function

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
import { startWaitAction, endWaitAction } from '../reducers';
 
const createWaiterMiddleWare = (extraArgument) => {
  return ({ dispatch, getState }) => (next) => (action) => {
    if (typeof action === 'object' && typeof action.callback === 'function') {
      dispatch(startWaiterAction(action.type.toString()))
      // check callback is Generator function
      if (action.callback.prototype && action.callback.prototype.toString() === '[object Generator]') {
        return dispatch({ ...action.action, continue: true })
      }
 
      return action.callback(dispatch, getState, extraArgument);
 
    }
    if (
      typeof action.type === 'string' &&
      (action.type.endsWith('success/@@end') ||
        action.type.endsWith('error/@@end'))
    ) {
      dispatch(
        endWaitAction(
          action.type
            .replace(/(?:[^\]].*?\]\s+?)(.*)/, '$1')
            .replace(/\/success\/@@end|\/error\/@@end/, ''),
        ),
      );
    }
    return next(action);
  };
};
 
const waiter = createWaiterMiddleWare();
waiter.withExtraArgument = createWaiterMiddleWare;
export default waiter;

Với đoạn mã trên, mình có cập nhật thêm là callback của action là 1 generator function thì mình sẽ cập nhật trạng thái tải của action là bắt đầu, và recall lại action với tham số được thêm là continue = true, để nó thực hiện trực tiếp worker saga như ban đầu. Vậy là mình đã xử lý xong vụ tải trong redux-saga

Mình sẽ cập nhật lại package redux-waiters và thêm hướng dẫn tích hợp khi dùng redux-saga

Example này mình cung cấp có 3 loại action
1. Multiply counter: redux-thunk bình thường
2. Desc counter: redux-waiters
3. Incr counter: redux-waiter cho saga

Link github: https://github.com/truongluu/redux-waiters-with-saga-example

Tags: reduxredux-actredux-sagaredux-thunkredux-waiters
Previous Post

Quản lý trạng thái tải của ứng dụng trong create-react-app

Next Post

Redux Saga phần I (Giới thiệu)

truongluu

truongluu

Next Post
Redux Saga phần I (Giới thiệu)

Redux Saga phần I (Giới thiệu)

Comments 1

  1. Pingback: Redux Saga phần III (Tips khi làm việc) - Lưu Xuân Trường's Blog

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

I will always choose a lazy person to do a difficult job. Because, he will find an easy way to do it

Bill Gates

Quotations

About me

Field of interests: Svelte, ReactJS, Angular, VueJS, React Native, Flutter, NodeJS, MongoDB, Message Broker, WordPress, AdonisJS, NestJS, NuxtJS, Docker, Microservice, Arduino, Game HTML5. Hope to share my experiences with everybody

Recent Posts

  • Styled components trong ReactJS
  • Frontity cơ bản phần I (Tạo và chạy dự án)
  • React framework for WordPress
  • How to run bash script in NodeJS
  • Thiết lập việc ưu tiên gọi saga worker trong redux-saga

Recent Comments

  • truongluu on Giới thiệu về UmiJS P2 (Cấu trúc thư mục, cấu hình thường dùng)
  • Hung on Giới thiệu về UmiJS P2 (Cấu trúc thư mục, cấu hình thường dùng)
  • Redux Saga phần III (Tips khi làm việc) - Lưu Xuân Trường's Blog on Quản lý trạng thái tải khi dùng redux-saga
  • Redux Saga phần II (Các khái niệm cơ bản) - Lưu Xuân Trường's Blog on Cheatsheets Non Blocking, Blocking Redux Saga
  • truongluu on Giới thiệu về UmiJS P4 (Server Side Rendering)

Archives

  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • March 2020
  • February 2020
  • January 2020
  • June 2019
  • May 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • April 2018
  • March 2018

Categories

  • Angular
  • Arduino
  • Backend
  • Câu Hỏi Phỏng Vấn
  • CSS
  • Ebook
  • Frontend
  • Frontity
  • Góc Ngoài Lề
  • How to
  • IOS
  • IQ Test
  • Javascript
  • Kinh nghiệm
  • Kinh nghiệm làm việc
  • Máy chủ
  • MongoDB
  • NestJS
  • NodeJS
  • NuxtJS
  • Plugins
  • React Native
  • React Native
  • ReactJS
  • Redis
  • Redux-Saga
  • RxJS
  • Tutorials
  • UmiJS
  • Uncategorized
  • VueJS
  • WordPress

Friends

Phu's blog
  • Giới thiệu về UmiJS P1 (Tổng quan về umiJS)

    Giới thiệu về UmiJS P1 (Tổng quan về umiJS)

    0 shares
    Share 0 Tweet 0
  • RxJS toàn tập (P1 giới thiệu RxJS là gì)

    0 shares
    Share 0 Tweet 0
  • Giới thiệu về UmiJS P2 (Cấu trúc thư mục, cấu hình thường dùng)

    0 shares
    Share 0 Tweet 0
  • Redux Saga phần I (Giới thiệu)

    0 shares
    Share 0 Tweet 0
  • Giới thiệu về UmiJS P3 (Permission routing)

    0 shares
    Share 0 Tweet 0

About me

Lưu Xuân Trường

Field of interests: Svelte, ReactJS, Angular, VueJS, React Native, Flutter, NodeJS, MongoDB, Message Broker, WordPress, AdonisJS, NestJS, NuxtJS, Docker, Microservice, Arduino, Game HTML5. Hope to share my experiences with everybody

© 2020 https://luuxuantruong.info

No Result
View All Result
  • Trang chủ
  • Backend
    • Laravel
    • Golang
    • NodeJS
    • MongoDB
    • Redis
    • WordPress
      • Kinh nghiệm
      • Plugins
  • Frontend
    • CSS
    • Javascript
      • ReactJS
      • UmiJS
      • VueJS
      • NuxtJS
      • Angular
      • RxJS
    • Game HTML5
  • Mobile
    • React Native
    • IOS
    • Android
    • Flutter
  • Tutorials
    • Redux-Saga
  • How to
  • Góc Ngoài Lề
    • Sống Chậm Nghĩ Sâu
    • Câu Hỏi Phỏng Vấn
    • IQ Test
  • Liên Hệ

© 2020 https://luuxuantruong.info

Welcome Back!

Login to your account below

Forgotten Password?

Create New Account!

Fill the forms below to register

All fields are required. Log In

Retrieve your password

Please enter your username or email address to reset your password.

Log In