ECMAScript 7.0 +

ES2017标准引入了诸多更实用的语法,如引入了async/await函数、幂运算符、Null传导运算符?.、装饰器等。

async/await 异步编程终级解决方案

async函数就是Generator函数的语法糖

async函数返回一个promise对象,并且把内部的值进行promise的封装,当async函数执行时遇到await就会先返回,等到异步操作完成,再接着执行函数体后面的语句,如果函数中return一个直接量,async会把这个直接量通过Promise.resolve()封装成Promise对象,在没有await的情况下执行async函数,它会立即执行,返回一个promise对象,不会阻塞后面的语句

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
// async/await 与 generator函数对比
var fs = require('fs');
var readFile = function (fileName){
return new Promise(function (resolve, reject){
fs.readFile(fileName, function(error, data){
if (error) reject(error)
resolve(data)
})
})
}
// Generator * yield 解决异步
var gen = function* (){
var f1 = yield readFile('/etc/fstab')
var f2 = yield readFile('/etc/shells')
console.log(f1.toString())
console.log(f2.toString())
}
// async await 解决异步
var asyncReadFile = async function (){
var f1 = await readFile('/etc/fstab')
var f2 = await readFile('/etc/shells')
console.log(f1.toString())
console.log(f2.toString())
}
/* async函数就是将Generator函数的星号*换成async,将yield换成await
async 的改进:1. 比起星号和yield语义更清楚了,async表示函数里有异步操作,await表示
后面的代码需要等待结果 2. async函数返回值是promise对象,使用then指定下一步操作 */

  • await关键字只能放到async函数里面,不可以脱离async单独使用,等待后面的promise对象执行完毕,然后拿到promise resolve 的值并进行返回,返回值拿到之后,它继续向下执行
  • await后面一定是Promise对象,如果不是会自动包装成Promise对象
  • await如果它等到的不是一个Promise对象,那await表达式的运算结果就是它等到的东西。
  • await如果它等到的是一个Promise对象,await会阻塞后面的代码,等着Promise对象resolve,然后得到resolve的值,作为await表达式的运算结果

    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
    // async 返回 promise 对象
    async function test(){
    return 4
    }
    console.log(test()) // Promise {<resolved>: 4}
    test().then(res => {console.log(res)}) // 4
    async function test1(){
    return new Promise((resolve, reject) =>{
    resolve(4)
    })
    }
    console.log(test1()) // Promise {<pending>}
    test1().then(res => {console.log(res)}) // 4

    // async 与 await 的使用
    function getGoodsId() {
    return new Promise(resolve => {
    setTimeout(() => resolve("商品id"), 1000)
    })
    }
    // 也可以使用如下写法
    // async function getGoodsId() {
    // await new Promise(resolve => {
    // setTimeout(() => resolve("商品id"), 1000)
    // })
    // }
    async function test() {
    console.log(await getGoodsId())
    }
    test() // 商品id
  • await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try…catch 代码块中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    async function fun() {
    try {
    await asyncFun()
    } catch (err) {
    console.log(err)
    }
    }
    // 另一种写法
    async function myFunction() {
    await asyncFun().catch(function (err){
    console.log(err)
    })
    }
  • async/await遇上map的遍历操作时,当async函数被执行时,将立即返回pending状态的Promise,因此,在map循环时,不会等待 await操作完成,而是直接进入下一次循环。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    let arr = [1, 2, 3]
    let res = arr.map(value => {
    return value * 2
    })
    console.log(res) // [2, 4, 6]

    let arr1 = [1, 2, 3]
    let res1 = arr1.map(async value => {
    return value * 2
    })
    console.log(res1) //  [Promise, Promise, Promise]
    // 使用 Promise.all() 将async返回的promise对象数组依次执行

    let arr1 = [1, 2, 3]
    let res1 = await Promise.all(arr1.map(async value => {
    return value * 2
    }))
    console.log(res1) //  [2, 4, 6]

BigInt

1
2
3
4
5
6
7
8
9
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992
const big1 = BigInt(Number.MAX_SAFE_INTEGER)
// BigInt 只能和 BigInt 类型进行运算 不能和其他类型进行运算
// console.log(big1 + 2); // Cannot mix BigInt and other types
// BigInt两种使用方式 BigInt(2) 或 2n
console.log(big1 + BigInt(2)); // 9007199254740993n
console.log(big1 + 2n); // 9007199254740993n
console.log(typeof (big1 + 2n)); // bigint

幂运算 **

1
2
3
4
5
// n**m 等同于 Math.pow(n, m)  n的m次方
console.log(2**5) // 32
console.log(Math.pow(2, 5)) // 32
// **运算是右结合的 4**3**2 ===> 4**(3**2) ===> 4**9
console.log(4**3**2) // 262144 不是(4**3)**2 4096

Null 传导运算符 ?.

如果读取对象内部的某个属性,往往需要判断该对象是否存在,该属性的上层属性是否存在

1
2
3
4
const obj = { teacher: {info: {age: 22}} }
const age = (obj && obj.teacher && obj.teacher.info && obj.teacher.info.age) || 18
// 这样的层层判断非常麻烦,使用 ?. 简化 只要其中一个返回null或undefined,就不再往下运算
const age = obj?.teacher?.info?.age || 18

catch语句的参数

允许try...catch结构中的catch语句调用时不带参数

1
2
3
try {} catch (error) {} // 传统写法,catch语句必须有参数,用来接收try代码块抛出的错误
// 新的写法允许省略catch后面的参数
try {} catch {}

装饰器

装饰器可以修饰类 类的属性 类的原型上的方法 修饰的时候就是把这个类的属性传递给修饰的函数

-------------本文结束感谢您的阅读-------------
0%