Vue.js 2.0 foundation knowledge - modular development and advanced use of asynchronous programming

Vue.js 2.0 foundation knowledge - modular development and advanced use of asynchronous programming

Article directory

1. Modular development

Benefits of modular development: Everyone writes code following the same modular specification, which reduces communication costs and greatly facilitates mutual calls between modules

1.1 Classification of front-end modular development

       Common modular specifications: CommonJS, AMD, CMD, and ES6 Modules , among which CommonJS, AMD, and CMD are modular standards proposed by the community, which have certain differences and limitations, and are not common to browsers and servers. Standards such as:

  • AMD, CMD: JavaScript modularity for the browser
  • CommonJS: JavaScript modularity for the server

 

1.2 CommonJS

       node.js follows the CommonJS modular specification, and its core is import and export , among which:

  • Import other modules using the require method
  • The external shared members of the module use the module.export object

Import of CommonJS:

let {
    
    flag, add} = require('moduleA');

// 等同于
let _mA = require('moduleA');
let flag = _mA.flag;
let add = _mA.add;

CommonJS export:

module.export = {
    
    
  flag: true,
  add(a, b) {
    
    
    return a + b
  }
}

       

1.3 ES6 modular specification

The ES6 modular specification is a modular development specification common to both the browser and the server. Developers do not need to learn additional modular specifications such as AMD, CMD or CommonJS.

The ES6 modular specification defines:

  • Each JS file is an independent module
  • To import other module members use the import keyword
  • External shared module members use the export keyword

       

1.3.1 The basic syntax of ES6 modularization

ES6 modularity mainly includes 3 usages:

Default export and default import

②On -demand export and on-demand import

③Directly import and execute the code in the module

       

1. Default export and default import

Default export syntax :export default 默认导出的成员

let n = 10;
let age = 20;
export default = {
    
    
    n,
    age
}

Default import syntax:import 接收名称 from '模块标识符'

import obj from './test.js'

Note: In each module, only one export default is allowed, otherwise an error will be reported

       

2. On-demand export and on-demand import

On-demand export syntax:export 按需导出的成员

export let s1 = 'aaa'
export let s2 = 'ccc'
export function say() {
    
    }

// 或者
let s1 = 'aaa'
let s2 = 'ccc'
function say() {
    
    }

export {
    
    s1, s2, say}

Import syntax on demand:import { 按需导入成员 } from '模块标识符'

import {
    
     s1, s2 as str2 } from './test.js'

Notice:

  • Multiple on-demand exports can be used in each module
  • Member names imported on demand must be consistent with names exported on demand
  • When importing on demand, you can use the as keyword to rename
  • On-demand imports can be used with default imports

       

3. Directly import and execute the code in the module

       If you just want to simply execute the code in the module , you don't need to get the externally shared members of the module. At this point, the module code can be directly imported and executed

// module.js
for(let i = 0; i < 3; i++) {
    
    
    console.log(i);
}
// 其他模块中
// 直接导入并执行模块代码,不需要得到模块中向外共享的成员
import './module.js'

       

2. Promise

2.1 Read file content asynchronously based on then-fs

       Since the fs module officially provided by node.js only supports reading files in the form of a callback function and does not support the calling method of Promise, the command needs to npm install then-fsbe support reading the content of the file based on the Promise method.

       

2.2 Basic use of then-fs

       Call the readFile() method provided by then-fs to read the content of the file asynchronously, and its return value is the instance object of Promise . So you can call the .then() method to specify the success and failure callback functions for each Promise asynchronous operation.

import thenFs from 'then-fs'

thenFs.readFile('./files/1.txt', 'utf-8').then(r1 => {
    
     console.log(r1); }, err1 => {
    
     console.log(err1.message); });

thenFs.readFile('./files/2.txt', 'utf-8').then(r2 => {
    
     console.log(r2); }, err2 => {
    
     console.log(err2.message); });

thenFs.readFile('./files/3.txt', 'utf-8').then(r3 => {
    
     console.log(r3); }, err3 => {
    
     console.log(err3.message); });

Note: The above code cannot guarantee the order of reading files and needs further improvement!

       

2.3 Features of the .then() method

       If a new Promise instance object is returned in the previous .then() method, you can continue processing through the next .then() method . The problem of callback hell can be solved by chaining calls of the .then() method.

       

2.4 Read the file content sequentially based on Promise

Promise supports chain calls, which can solve the problem that the above files are not read in order:

thenFs.readFile('./files/1.txt', 'utf-8')
  .then((r1) => {
    
    
    console.log(r1)
    return thenFs.readFile('./files/2.txt', 'utf-8') // 在第一个 .then中返回一个新的 promise 实例对象
  })
  .then((r2) => {
    
    
    console.log(r2)
    return thenFs.readFile('./files/3.txt', 'utf-8')
  })
  .then((r3) => {
    
    
    console.log(r3)
  })

       

2.5 Promise.all()

       The Promise.all() method will initiate parallel Promise asynchronous operations, and the next .then operation (waiting mechanism) will not be executed until all asynchronous operations are completed . Sample code:

// 1.定义一个数组,存放3个读文件的异步操作
const promiseArr = [
  thenFs.readFile('./files/1.txt', 'utf-8'),
  thenFs.readFile('./files/2.txt', 'utf-8'),
  thenFs.readFile('./files/3.txt', 'utf-8')
]

// 2.将 promise 数组作为promise.all()的参数
Promise.all(promiseArr)
  .then(([r1, r2, r3]) => {
    
     // 2.1 所有文件读取成功(等待机制)
    console.log(r1, r2, r3)
  })
  .catch(err => {
    
     // 2.2 捕获 Promise 异步操作中的错误
    console.log(err.message)
  })

Note: The order of the Promise instances in the array is the order of the final results

       

2.6 Promise-based encapsulation method for reading files

Method encapsulation requirements:

① The name of the method should be defined as getFile

② The method accepts a formal parameter fpath , indicating the path of the file to be read

The return value of the method is a Promise instance object

       

2.6.1 Basic definition of getFile method

function getFile(fpath) {
    
    
  return new Promise() // 只是创建了形式上的异步操作
}

Note: new Promise() here just creates a formal asynchronous operation

       

2.6.2 Create specific asynchronous operations

       If you want to create a specific asynchronous operation, you need to pass a function function during the new Promise() constructor to define the specific asynchronous operation inside the function function

function getFile(fpath) {
    
    
  return new Promise(function() {
    
    
    // 表明这是个具体的、读文件的异步操作
    fs.readFile(fpath, 'utf-8',(err, data) => {
    
     })
  })
}

       

2.6.3 Get the two actual parameters of .then

       The success and failure callback functions specified by .then() can be received in the formal parameters resolve and reject of the function. The sample code is as follows:

function getFile(fpath) {
    
    
  return new Promise(function(resolve,reject) {
    
    
    // 表明这是个具体的、读文件的异步操作
    fs.readFile(fpath, 'utf-8',(err, data) => {
    
    
        if(err) return reject(err)
        resolve(data)
    })
  })
}

// getFile 方法调用
getFile('./files/1.txt').then(成功的回调函数,失败的回调函数)

       

3. async/await

3.1 The concept of async/await

       async/await is a new syntax introduced by ES8 to simplify Promise asynchronous operations .

       The method returns a Promise instance, which can be decorated with await. If the inner method is decorated with await, the outer method must be decorated with async

// 按照顺序读取文件 1、2、3 的内容
async function getAllFile() {
    
    
  const r1 = await thenFS.readFile('./files/1.txt','utf8')
  console.log(r1);
  const r2 = await thenFS.readFile('./files/1.txt','utf8')
  console.log(r2);
  const r3 = await thenFS.readFile('./files/1.txt','utf8')
  console.log(r3);
}

getAllFile()

Notice:

① If await is used in the function, the function must be modified by async

② In the async method, the code before the first await will be executed synchronously , and the code after await will be executed asynchronously

       

4. Event Loop

4.1 JavaScript is a single-threaded language

       JavaScript is a single-threaded execution programming language, that is, only one thing can be done at a time. The problem of single-threaded execution task queue: If the previous task is very time-consuming, the subsequent task will have to wait forever, resulting in the problem of program suspended animation ,

       

4.2 Synchronous tasks and asynchronous tasks

       In order to prevent the problem of program suspended animation caused by a time-consuming task , JavaScript divides the tasks to be executed into two categories:

Synchronous task (synchronous)

  • Also known as non-time-consuming tasks , they refer to those tasks that are queued for execution on the main thread
  • The next task can only be executed after the previous task is completed

②Asynchronous task (asynchronous)

  • Also called time-consuming tasks , asynchronous tasks are entrusted by JavaScript to the host environment (browser, node, etc.) for execution
  • When the asynchronous task is executed, the JavaScript main thread will be notified to execute the callback function of the asynchronous task

       

4.3 The execution process of synchronous tasks and asynchronous tasks

① Synchronous tasks are executed sequentially by the JavaScript main thread

② Asynchronous tasks are delegated to the host environment for execution

③ The callback function corresponding to the completed asynchronous task will be added to the task queue for execution

④ After the execution stack of the JavaScript main thread is cleared, it will read the callback functions in the task queue and execute them sequentially

⑤ JavaScript main thread repeats step 4

       

4.4 The basic concept of EventLoop

image-20211110104006223

       The JavaScript main thread reads the callback function of the asynchronous task from the "task queue" and puts it in the execution stack for one execution . This process is cyclical, so the entire operating mechanism is also called EventLoop (event loop)

       

4.4.1 Combining EventLoop to analyze the output sequence (interview questions)

import thenFs from 'then-fs'

console.log('A')
thenFs.readFlie('./files/1.txt', 'utf8').then(data => {
    
    
  console.log('B')
})
setTimeout(() => {
    
    
  console.log('C')
}, 0)
console.log('D')

// A
// D
// C
// B

analyze:

  • A and D are synchronous tasks and will be executed in sequence according to the sequence of codes
  • C and B are asynchronous tasks . Their callback functions will be added to the task queue and wait for the main thread to be idle before executing

       

5. Macro tasks and micro tasks

image-20211110111234833

JavaScript further divides asynchronous tasks, and asynchronous tasks are divided into two categories, namely:

① Macro task (macrotask)

  • Asynchronous Ajax requests
  • setTimeout、setInterval
  • file operation
  • other macro tasks

② Micro task (micro task)

  • Promise.then、.catch 和 .finally
  • Promise.nextTick
  • other microtasks

       

5.1 Execution order of macrotasks and microtasks

image-20211110111351792

  • After each macrotask is executed, it will check whether there are microtasks to be executed . If so, after executing all microtasks, continue to execute the next macrotask
  • When executing for the first time, when macro tasks and micro tasks exist at the same time, the micro tasks are executed first

       

5.2 Classical Interview Questions for Macro-tasks and Micro-tasks

Interview question 1: Analyze the sequence of the following code output

import thenFs from 'then-fs'

setTimeout(function() {
    
    
  console.log('1')
})

new Promise(function(resolve) {
    
    
  console.log('2')
  resolve()
}).then(function() {
    
    
  console.log('3')
})

console.log('4')
// 2
// 4
// 3
// 1

image-20211110112830941
analyze:

  1. Execute all sync tasks first
  2. Re-execute the microtask
  3. Execute the macro task again

       

Interview question 2: Analyze the order of the following code output

console.log('1')
setTimeout(function() {
    
    
  console.log('2')
  new Promise(function(resolve) {
    
    
    console.log('3')
    resolve()
  }).then(function() {
    
    
    console.log('4')
  })
})

new Promise(function(resolve) {
    
    
  console.log('5')
  resolve()
}).then(function() {
    
    
  console.log('6')
})

setTimeout(function() {
    
    
  console.log('7')
  new Promise(function(resolve) {
    
    
    console.log('8')
    resolve()
  }).then(function() {
    
    
    console.log('9')
  })
})

// 1
// 5
// 6
// 2
// 3
// 4
// 7
// 8
// 9

       

Six, API interface case

Case requirements: API interface service based on MySQL database + Express to provide external user list. The techniques used are as follows:

  • Third-party packages express and mysql2
  • ES6 Modularity
  • Promise
  • async/await

       

6.1 Main implementation steps

  1. Build the basic structure of the project
  2. Create a basic server
  3. Create db database operation module
  4. Create user_ctrl business module
  5. Create user_router routing module

       

6.2 Build the basic structure of the project

① Enable ES6 modular support

  • Declared in package.json"type":"module"

② Install third-party dependent packages

       

6.3 Create a basic express server

import express from 'express'

const app = express()

app.listen(80, () => {
    
    
  console.log('server running at http://127.0.0.1:80');
})

       

6.4 Create db database operation module

import mysql from 'mysql2'

const pool = mysql.createPool({
    
    
  host: '127.0.0.1',
  port: 3306,
  database: 'my_db_01', // 要操作的数据库名称
  user: 'root',
  password: 'admin123'
})

// 默认导出一个支持 Promise API 的 pool
export default pool.promise()

       

6.5 Create user_ctrl business module

// 获取所有用户的列表数据
import db from '../db/index.js'

// 按需导出
export async function getAllUser(req, res) {
    
    
    // db.query() 函数的返回值时 Promise 的实例对象,因此可以使用async/await 进行简化
  const [rows] = await db.query('select id, username, nickname from ev_users')
  res.send({
    
    
    status: 0,
    message: '获取用户数据列表成功',
    data: rows
  })
}

       

6.6 Create user_router routing module

// user_router.js
import express from 'express'
// 从 user_ctrl.js 中按需导入 getAllUser 函数
import {
    
     getAllUser } from '../controller/user_ctrl'

// 创建路由对象
const router = new express.Router()
// 挂载路由规则
router.get('/user', getAllUser)

export default router

       

6.7 Import and mount the routing module

//app.js
import express from 'express'
// 1.使用默认导入语法,导入路由对象
import userRouter from './router/user_router.js'
const app = express()

// 2. 挂载用户路由模块
app.use('/api', userRouter)

app.listen(80, () => {
    
    
  console.log('server running at http://127.0.0.1:80');
})

Guess you like

Origin blog.csdn.net/weixin_45950819/article/details/121263256