Saturday, February 27, 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

Child Process trong Nodejs là gì? Khi nào thì cần sử dụng

truongluu by truongluu
10/10/2020
in NodeJS
Reading Time: 5min read
0 0
0
Phân biệt Fork và Spawn trong Redux-Saga
0
SHARES
297
VIEWS
Share on FacebookShare on Twitter

Trong quá trình làm việc với nodeJS, bạn sẽ gặp 1 vấn đề khi gọi tới một hàm xử lý tính toán tốn nhiều thời gian. Ví dụ: gọi một API cho phép bạn lấy về danh sách đơn hàng phân trang và thống kê có bao nhiêu đơn hàng đã hoàn thành, đã giao hàng hoặc huỷ… (theo mốc thời gian là tất cả hoặc theo tháng năm…). Nếu dữ liệu của bạn nhiều thì việc gọi API để tải dữ liệu về bạn phải đợi vài giây, để tải được danh sách và kết quả thống kê, điều này làm cho ứng dụng của bạn có vẻ lắc hoặc giựt, không mượt mà.

JavaScript
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module.exports = {
fetchOrder: async (req, res) => {
    try {
      let pageSize = 10;
      let currentPage = 1;
      if (typeof req.body['pageSize'] !== 'undefined') {
        pageSize = parseInt(req.body.pageSize);
      }
 
      if (typeof req.body['currentPage'] !== 'undefined') {
        currentPage = parseInt(req.body.currentPage);
      }
 
      let orderQuery = { orderStatus: 'publish' };
      let aggregateorderQuery = {orderStatus: 'publish'};
      if( typeof req.body['orderStatus'] !== 'undefined' && req.body['orderStatus'] ) {
        orderQuery.orderStatus = req.body['orderStatus'];
        aggregateorderQuery.orderStatus = req.body['orderStatus'];
      }
      
      let query_date = {};
      if (typeof req.body['from'] !== 'undefined' && req.body['from'] !== null) {
        query_date = { ...query_date, '$gte': new Date(moment(`${req.body['from']} 00:00:00`, 'MM/DD/YYYY H:mm:ss')) };
      }
      if (typeof req.body['to'] !== 'undefined' && req.body['to'] !== null) {
        query_date = { ...query_date, '$lte': new Date(moment(`${req.body['to']} 23:59:59`, 'MM/DD/YYYY H:mm:ss')) };
      }
 
      if (!_.isEmpty(query_date)) {
        orderQuery = { ...orderQuery, createdAt: query_date };
        aggregateorderQuery = { ...aggregateorderQuery, createdAt: query_date };
      }
 
      if (typeof req.body['paymentMethod'] !== 'undefined'
        && req.body.paymentMethod !== 'all'
      ) {
        orderQuery.paymentMethod = req.body.paymentMethod;
        aggregateorderQuery.paymentMethod = req.body.paymentMethod;
      }
 
      if (typeof req.body['orderId'] !== 'undefined'
      ) {
        const orderId = slug(req.body.orderId, { lowercase: true });
        orderQuery.orderId = new RegExp(`${orderId}`, "i");
        aggregateorderQuery.orderId = new RegExp(`${orderId}`, "i");
      }
 
      if (typeof req.body['paymentStatus'] !== 'undefined'
        && req.body.paymentStatus !== 'all'
      ) {
        let paymentStatus = req.body['paymentStatus'];
        paymentStatus = paymentStatus.split('|');
        orderQuery.paymentStatus = {
          $in: paymentStatus
        };
        orderQuery.status = {
          $ne: 'cancel'
        }
      }
      const list = await Order.find({ ...orderQuery })
        .populate('member')
        .populate('staff')
        .limit(pageSize)
        .skip((currentPage - 1) * pageSize)
        .sort('-createdAt');
      const total = await Order.find({ ...orderQuery }).count();
 
      
      // Order status counter
      const order_status_counter = await OrderStatusCounter
        .aggregate()
        .match({
          ...aggregateorderQuery
        })
        .group({
          _id: {
            status: '$status'
          },
          count: { $sum: 1 }
        })
        .project({
          "_id": 0,
          "status": "$_id.status",
          "count": "$count"
        });
 
      
      // Order status extend counter
      const order_status_extend_counter = await Order
        .aggregate()
        .match({
          ...aggregateorderQuery,
          status: 'finish',
          transferredProfit: false,
          netProfit: {
            $gt: 0
          }
        })
        .group({
          _id: '',
          count: { $sum: 1 }
        })
        .project({
          "_id": 0,
          "status": "not_transferred_profit",
          "count": "$count"
        });
      return {
        order_status_counter,
        order_status_extend_counter,
        data: {
          list,
          pagination: {
            currentPage,
            pageSize,
            total,
            current: currentPage,
          }
        }
 
      };
    } catch (e) {
    }
  }
}

Đoạn thống kê của bạn nó nằm ở phần mã này:

JavaScript
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
// Order status counter
      const order_status_counter = await OrderStatusCounter
        .aggregate()
        .match({
          ...aggregateorderQuery
        })
        .group({
          _id: {
            status: '$status'
          },
          count: { $sum: 1 }
        })
        .project({
          "_id": 0,
          "status": "$_id.status",
          "count": "$count"
        });
 
      
      // Order status extend counter
      const order_status_extend_counter = await Order
        .aggregate()
        .match({
          ...aggregateorderQuery,
          status: 'finish',
          transferredProfit: false,
          netProfit: {
            $gt: 0
          }
        })
        .group({
          _id: '',
          count: { $sum: 1 }
        })
        .project({
          "_id": 0,
          "status": "not_transferred_profit",
          "count": "$count"
        });

và để chạy một API như vậy bạn sẽ phải đợi vài giây cho một lần yêu cầu

Để giải quyết vấn đề này, mình sài tới một API của nodeJS đó là child_process. Vậy child process trong nodeJS là gì? khi nào cần sử dụng. Với child_process nó cho phép bạn thực thi 1 tiến trình con để xử lý việc tính toán phức tạp, bằng cách tách hàm lấy dữ liệu phân trang ra 1 API và hàm tính toán thống kê ra 1 API, và việc tính toán thống kê sẽ được 1 tiến trình con xử lý (ở đây mình sài fork). Khi sài như vậy việc trả về danh sách của bạn và việc tính chạy chạy song song và không block lẫn nhau, ứng dụng vẫn tải nhanh và việc tải thông kê nào xử lý xong nó sẽ load dữ liệu sau, làm cho ứng dụng của bạn có vẻ mượt mà hơn

JavaScript
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
44
45
46
47
48
module.exports = {
    orderAggregation: async (req, res) => {
        let pageSize = 10;
        let currentPage = 1;
        if (typeof req.body['pageSize'] !== 'undefined') {
            pageSize = parseInt(req.body.pageSize);
        }
 
        if (typeof req.body['currentPage'] !== 'undefined') {
            currentPage = parseInt(req.body.currentPage);
        }
 
        let orderQuery = {};
        let aggregateorderQuery = {};
 
        let query_date = {};
        if (typeof req.body['from'] !== 'undefined' && req.body['from'] != null) {
            query_date = { ...query_date, '$gte': `${req.body['from']} 00:00:00` };
        }
        if (typeof req.body['to'] !== 'undefined' && req.body['to'] != null) {
            query_date = { ...query_date, '$lte': `${req.body['to']} 23:59:59` };
        }
        if (!_.isEmpty(query_date)) {
            orderQuery = { ...orderQuery, createdAt: query_date };
            aggregateorderQuery = { ...aggregateorderQuery, createdAt: query_date };
        }
 
 
        if (typeof req.body['orderId'] !== 'undefined'
        ) {
            const orderId = slug(req.body.orderId, { lowercase: true });
            orderQuery.orderId = new RegExp(`${orderId}`, "i");
            aggregateorderQuery.orderId = new RegExp(`${orderId}`, "i");
        }
 
        const orderAggregationPath = path.resolve(__dirname, '..', 'libs/orderAggregation.js');
        const child_process = cp.fork(orderAggregationPath);
        child_process.send({ aggregateorderQuery });
 
        const data = await new Promise((resovle) => {
            child_process.on('message', (data) => {
                child_process.kill('SIGINT');
                return resovle(data);
            })
        });
        return data;
    }
}

Đoạn mã thống kê bên trên

JavaScript
1
2
3
4
5
6
7
8
9
10
const orderAggregationPath = path.resolve(__dirname, '..', 'libs/orderAggregation.js');
        const child_process = cp.fork(orderAggregationPath);
        child_process.send({ aggregateorderQuery });
 
        const data = await new Promise((resovle) => {
            child_process.on('message', (data) => {
                child_process.kill('SIGINT');
                return resovle(data);
            })
        });

Nội dung đoạn mã của file orderAggregation.js

JavaScript
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
const mongoose = require('mongoose');
require('./db');
const {
    Order
} = require('../models');
 
process.on('message', async (data) => {
    let { aggregateorderQuery}  = data;
    if( typeof aggregateorderQuery['createdAt'] !== 'undefined') {
        aggregateorderQuery['createdAt']['$gte'] = new Date(aggregateorderQuery['createdAt']['$gte']);
        aggregateorderQuery['createdAt']['$lte'] = new Date(aggregateorderQuery['createdAt']['$lte']);
    }
    const all_finish_order_statistics = await Order
        .aggregate()
        .match({
            ...aggregateorderQuery,
            ...memberQuery,
            status: 'finish',
            orderStatus: 'publish'
        })
        .group(
            {
                _id: '',
                totalPrice: {
                    $sum: '$totalPrice'
                }
            }
        )
        .project({
            _id: 0,
            totalPrice: '$totalPrice'
        });
    const all_order_statistics = await Order
        .aggregate()
        .match({
            ...aggregateorderQuery,
            orderStatus: 'publish',
            status: {
                $ne: 'cancel'
            }
        })
        .group(
            {
                _id: '',
                totalPrice: {
                    $sum: '$totalPrice'
                }
            }
        )
        .project({
            _id: 0,
            totalPrice: '$totalPrice'
        });
    
    process.send({
        all_finish_order_statistics,
        all_order_statistics
    });
});
 
process.on('exit', (code) => {
    console.log(`Exit process ${code}`);
});

cho phép bạn xử lý việc gọi hàm tốn nhiều thời gian, bằng cách gọi child_process.fork(absolute_path). và sau khi đoạn mã bên trong file orderAggregation xử lý xong thì child_process nó nhận kết quả trả về bằng phương thức

JavaScript
1
2
3
4
child_process.on('message', (data) => {
                child_process.kill('SIGINT');
                return resovle(data);
            })

Ở trên mình sài một Promise để xử lý có kết quả trả về từ child_process và trả về dữ liệu cho client.

Chú ý khi sài child_process.fork là trong sự kiện on(‘message’) bạn cần gọi 1 hàm child_process.kill(‘SIGINT’) để huỷ tiến trình con này.

Tags: child_processnodeJS
Previous Post

RxJS toàn tập (P2 hướng dẫn cài đặt RxJS)

Next Post

Phân biệt Fork và Spawn trong Redux-Saga

truongluu

truongluu

Next Post
Phân biệt Fork và Spawn trong Redux-Saga

Phân biệt Fork và Spawn trong Redux-Saga

Leave a Reply Cancel reply

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

An intelligent person is like a river, the deeper the less noise.

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

  • Code push in React Native
  • What’s middleware? How does it work?
  • Styled components trong ReactJS
  • Frontity cơ bản phần I (Tạo và chạy dự án)
  • React framework for WordPress

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

  • February 2021
  • January 2021
  • 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

  • AdonisJS
  • 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ủ
  • Mobile
  • MongoDB
  • NestJS
  • NodeJS
  • NuxtJS
  • Plugins
  • React Native
  • React Native
  • ReactJS
  • Redis
  • Redux-Saga
  • RxJS
  • Tutorials
  • UmiJS
  • Uncategorized
  • VueJS
  • WordPress

Friends

Phu's blog
  • RxJS toàn tập (P1 giới thiệu RxJS là gì)

    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 P1 (Tổng quan về umiJS)

    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
  • Một số câu hỏi phỏng vấn frontend developer

    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