Hướng dẫn dùng getasync JavaScript

Nội dung bài viết

Video học lập trình mỗi ngày

Lập trình đồng bộ hay bất đồng bộ không đơn giản như những gì được viết trong nhiều blog, đó chỉ là lý thuyết, vậy làm sao chúng ta biết được hiệu suất của nó thế nào đây?

Lưu ý: Đây là một trong những bài viết trong Serires Nodejs: Học 7 ngày

Là một lập trình viên bất cứ level nào bạn cũng hiểu về khái niệm lập trình đồng bộ và bất đồng bộ. Chúng ta chỉ hiểu nôm na rằng nếu lâp trình không đồng bộ thì sử dụng và thực hiện với sự trợ giúp của callbacks, Promise, async và await. Và hơn ai hết cả thảy chúng ta đều biết rằng không đồng bộ sẽ tốt hợn rất nhiều, vậy nó thực sự tốt như thế nào? Tôi sẽ làm một ví dụ giúp bạn hiểu rõ thực sự. Và cũng là để cho các bạn có thêm kiến thức nhằm có điểm công trong mắt nhà tuyển dụng vị trí back-end nodejs.

So sánh hiệu suất Async và Sync

Để so sánh hiệu suất giữa đồng bộ và bất đồng bộ, thì chúng tôi sẽ sử dụng package bcrypt và expressjs. Vì bcrypt có cung cấp các phương thức đồng bộ và không đồng bộ để băm một chuỗi nhất định. lấy nó làm ví dụ qủa là hợp lý. Ở đây không giải thích nhiều về 2 khái niệm Async và Sync chỉ tập trung test hiệu suất. OK!! 

Đầu tiên hãy install các packages:

AnonyStick$ npm i bcrypt express --save

added 39 packages, and audited 589 packages in 4s

5 packages are looking for funding
  run `npm fund` for details

2 high severity vulnerabilities

Some issues need review, and may require choosing
a different dependency.

Run `npm audit` for details.

## Tạo file app.js

const express = require('express')
const bcrypt = require('bcrypt')

const app = express()

app.get('/sync', (req, res) => {
    let hashed = bcrypt.hashSync('secret', 10)
    return res.send(hashed)
})

app.get('/async', async (req, res) => {
    let hashed = await bcrypt.hash('secret', 10)
    return res.send(hashed)
})

app.listen(3000, () => console.log('Server started on port 3000'))

Cần chú ý đoạn code trên, nếu bạn đủ trình độ thì bỏ qua khúc này, còn chưa hãy để tôi giải thích cho bạn. Chúng ta có 2 nhiệm vụ, đó là gọi hai routes là /sync/async. bcrypt.hashSync() là một method đồng bộ, và bcrypt.hash() không đồng bộ. Bây giờ chúng ta sẽ test hiệu suất hai routes này thông qua apache bench.

Apache bench là một công cụ để đánh giá các máy chủ HTTP.

Sync mode benchmark

Sủ dụng lệnh sau đây để test về đồng bộ

AnonyStick$ ab -k -c 20 -n 250 "http://localhost:3000/sync"

AnonyStick$ ab -k -c 20 -n 250 "http://localhost:3000/async"

Nếu vẫn chưa biết về apache bench thì hãy để tôt giải thích tiếp: 

  • ab: viết tắt của apache bench 
  • -k: Kích hoạt tính năng HTTP KeepAlive 
  • -c: Số lượng nhiều yêu cầu thực hiện cùng một lúc. 
  • -n: Số lượng yêu cầu thực hiện cho phiên đo điểm chuẩn 

Kết quả cho câu lênh trên được đưa ra dưới đây. Hay để ý hình ảnh chi tiết một chút 

Hướng dẫn dùng getasync JavaScript

SO SÁNH: Trước tiên tôi đã tổng kết cho bạn đọc nhanh nhất: 

Hướng dẫn dùng getasync JavaScript

Xem hình ảnh chúng ta có thể thấy rằng. Cơ chế async tốt hơn sync về tính trung bình xử lý đồng thời. 1446.324 so với 384.406. Và còn nhiều thông số khác nhỉnh hơn. Nếu bạn cảm thấy chưa thoả mãn, vui lòng đọc thêm thông tin về các chỉ số trên đó.

Tóm lại

So sánh để làm gì? Để luôn nhớ rằng sử dụng chế độ async khi mã của bạn cần thực hiện một số thao tác Blocking i/o vì nó không chặn Event Loop.

Giới thiệu về Jest

Jestjs là một JavaScript Testing Framework khá là dễ sử dụng và cài đặt, tuy nhiên vẫn đầy đủ tính năng để bạn có thể sử dụng

Hướng dẫn dùng getasync JavaScript
Bài viết này mình xin giới thiệu một số tính năng cơ bản của jest cùng với một số ví dụ.

Cài đặt

Cài đặt Jest khá đơn giản:

yarn add --dev jest

hoặc

npm install --save-dev jest

Sau đó thêm đoạn code sau vào file package.json:

{
  "scripts": {
    "test": "jest"
  }
}

Tiếp theo mình có ví dụ một file test: math.js

function sum(a, b) {
  return a + b;
}

const MathJS = {
  sum,
}

module.exports = MathJS;

Để viết test cho file trên mình tạo file test/math.test.js, đuôi file là test.js sẽ nói cho jest biết đây là file test của bạn.

const MathJS = require('../math');

it('Adds 1 + 1 to equals 2', () => {
  expect(MathJS.sum(1, 1)).toBe(2);
});

Sau đó chạy yarn test hoặc npm run test.

Hướng dẫn dùng getasync JavaScript

Các Matchers trong Jest

Ở trong đoạn code trên:

expect(MathJS.sum(1, 1)).toBe(2);

.toBe() chính là một matcher trong jest. Nó giống như phép so sánh bằng bình thường vậy. Ví dụ:

expect(result).toBe(2);
expect(result).toBe(true);
expect(result).toBe({a: 1, b: 2});

Tuy nhiên khi so sánh một Object bạn nên sử dụng .toEqual() Lý do là vì .toBe thực tế sử dụng === để so sánh và đưa ra kết quả. Và chúng ta đều biết trong javascript:

a = {};
b = {};
a === b;
=> false

Còn .toEqual() theo như Jest sẽ lần lượt kiểm tra tất các trường của Object, hoặc mảng để so sánh. Vì vậy thay vì viết:

expect(result).toBe({a: 1, b: 2});

Hãy viết:

expect(result).toEqual({a: 1, b: 2});

Ngoài ra còn các matchers khác:

Truthiness

  • toBeNull so sánh với giá trị null.
  • toBeUndefined so sánh với giá trị undefined.
  • toBeDefined là hàm cho kết quả ngược lại toBeUndefined.
  • toBeTruthy so sánh với giá trị true.
  • toBeFalsy so sánh với giá trị false.

Numbers

it('two plus two', () => {
  const value = 2 + 2;
  expect(value).toBeGreaterThan(3);
  expect(value).toBeGreaterThanOrEqual(3.5);
  expect(value).toBeLessThan(5);
  expect(value).toBeLessThanOrEqual(4.5);

  // toBe and toEqual are equivalent for numbers
  expect(value).toBe(4);
  expect(value).toEqual(4);
});

Đối với số thập phân, bạn nên sử dụng toBeCloseTo:

it('adding floating point numbers', () => {
  const value = 0.1 + 0.2;
  //expect(value).toBe(0.3);           This won't work because of rounding error
  expect(value).toBeCloseTo(0.3); // This works.
});

String

Bạn có thể kiểm tra một đoạn văn bản với regular expressions bằng toMatch:

it('there is no I in team', () => {
  expect('team').not.toMatch(/I/);
});

it('but there is a "stop" in Christoph', () => {
  expect('Christoph').toMatch(/stop/);
});

Array

Để kiểm tra giá trị có trong một mảng, bạn có thể dùng toContain:

const array = [1, 2, 10, 1000];
it('array has 1000 on it', () => {
  expect(array).toContain(1000);
});

Exceptions

Để kiểm tra một lỗi có thể xảy ra bạn có thể sử dụng toThrow:

function compileAndroidCode() {
  throw new ConfigError('you are using the wrong JDK');
}

test('compiling android goes as expected', () => {
  expect(compileAndroidCode).toThrow();
  expect(compileAndroidCode).toThrow(ConfigError);

  // You can also use the exact error message or a regexp
  expect(compileAndroidCode).toThrow('you are using the wrong JDK');
  expect(compileAndroidCode).toThrow(/JDK/);
});

Một số ví dụ

Test một action trong redux

const CHANGE_EMAIL = 'CHANGE_EMAIL';

function changeEmail(email) {
  return {
    type: CHANGE_EMAIL,
    email
  }
}

it('should render type and email of change email action', () => {
  const email = '';
  const expected = {
    type: CHANGE_EMAIL,
    email,
  }

  expect(changeEmail(email)).toEqual(expected);
});

Test một event trong Jquery

it('should fire a alert', () => {
  const alert = jest.fn();

  document.body.innerHTML =
    '
' + ' ' + '
'; $('#button').click(() => { alert('click'); }); $('#button').click(); expect(alert).toBeCalled(); // the mock function is called one time expect(alert.mock.calls.length).toBe(1); // The first argument of the first call to the function was click expect(alert.mock.calls[0][0]).toBe('click'); });

Bạn có thể thấy const alert = jest.fn();. Đây là một tính năng trong Jest giúp bạn mock một function. Hay mô phỏng lại hàm cần test.

Test với module axios

const axios = require('axios');

jest.mock('axios', () => ({
  get: jest.fn().mockResolvedValue({ data: { message: 'hello' }})
}));

test('mock axios.get', async () => {
  const response = await axios.get('https://test.com/t/1');
  expect(response.data).toEqual({ foo: 'bar' });
});

Trong ví dụ này mình đã mock module axios, và đặt giá trị trả về cho hàm get. Như vậy khi test bạn sẽ không cần phải gửi request thật, tránh mất thời gian. Các module khác bạn cũng có thể làm cách tương tự.

Blog của mình