您的位置:首页 > 大数据 > 人工智能

ES6系列 (05):async await

2020-12-14 22:20 796 查看

首先我们先来了解几个async基本知识点:

await
命令只能用在
async
函数之中,如果用在普通函数,就会报错

async
函数返回的是Promise 对象

  • 如果返回的是一个基本类型数据,
    async
    函数会先用
    Promise.resolve(...)
    将其包装为一个Promise对象再将其返回。
  • 如果无返回值,等同于直接返回
    Promise.resolve()
  • 如果返回的是一个Promise对象,则不做处理直接将其返回

await
命令后面可跟Promise对象或者任意表达式

  • 如果是Promise对象,则等待并返回该对象的结果
  • 如果是表达式,则等待并返回表达式的值

错误处理

如果

await
后面的Promise对象变为
rejected
状态 或者 async方法抛出异常,那么整个
async
函数则会中断执行,并且返回的 Promise 对象为
rejected
状态

  • Promise对象变为

    rejected
    状态:

    async function getTodo() {
    await new Promise(function (resolve, reject) {
    reject('异步操作出错了')
    })
    console.log('柏成大帅比')
    return '柏成'
    }
    
    getTodo().then(res => console.log('res',res))
    .catch(err => console.log('err',err))
    
    // err,异步操作出错了
  • async方法抛出异常:

    async function getTodo() {
    await new Promise(function (resolve, reject) {
    resolve('异步操作正常')
    })
    throw new Error('代码抛出异常')
    console.log('柏成大帅比')
    return '柏成'
    }
    
    getTodo().then(res => console.log('res',res))
    .catch(err => console.log('err',err))
    
    // err,Error: 代码抛出异常
    // at getTodo (js012-测试.html:11)

为了防止代码异常阻塞async函数的执行,我们可以使用

try...catch
方法, 如果
try
方法块中Promise对象变为
rejected
状态 或者 代码抛出异常,则仅仅中断
try
方法块的代码执行,并不会阻塞async函数的后续代码执行

async function getTodo() {
try {
const val1 = await getFirstVal()
const val2 = await getSecondVal()
const val1 = await new Promise(function (resolve, reject) {
reject('异步操作异常')
})
} catch (err) {
console.log(err);
}
console.log('柏成大帅比')
return 'hello world'
}

getTodo().then(res => console.log(res))
.catch(err => console.log(err))

// 异步操作异常
// 柏成大帅比
// hello world

实现休眠语法

记得之前做课设要实现一个着色格子板,要看到着色的过程,如何在本次着色后暂停一秒钟再执行下一次着色代码,就采用了下面的休眠方法

// 休眠方法
function sleep(interval) {
return new Promise(resolve => {
setTimeout(()=> resolve(), interval);
})
}

// 调用休眠方法
(async function () {
for(let i = 1; i <= 5; i++) {
console.log(i)
await sleep(1000)
}
})()

继发&并发

继发执行:异步操作存在先后顺序,等待上一个 await 执行完毕后,再接着下一个

async function getTodo() {
const val1 = await getFirstVal()
const val2 = await getSecondVal()
}

并发执行:异步操作相互独立,不存在依赖关系,可以同时触发,提高执行效率

// 如没有await关键字,遇到异步操作,将其挂起无需等待异步操作结果,转而继续执行下一行代码,基本等同于同时触发
const firstPromise = getFirstVal()
const secondPromise = getSecondVal()
const [val1, val2] = await Promise.all([firstPromise, secondPromise]);

// 或者

const [val1, val2] = await Promise.all([getFirstVal(), getSecondVal()]);

循环中的await

for语句、for/in语句、for/of语句
,会继发执行(等待上一个 await 执行完毕后,再接着下一个),没有任何叼毛问题,nice!

async function getTodo(arr) {
for (const item of arr) {
const res = await getSomething(item);
console.log(`res-${item}:`, res);
}

console.log('finished!');
}

getTodo([1,2,3])

// res-1:...
// res-2:...
// res-3:...
// finished!

forEach
map
,调用了callback回调函数,存在大大的副作用,强烈不建议在
forEach
map
等循环 ad8 中使用
await

async function getTodo(arr) {
await arr.forEach(async item => {
const res = await getSomething(item);
console.log(`res-${item}:`, res);
})

console.log('finished!');
}

getTodo([1,2,3])

// finished!
// res-2:...
// res-1:...
// res-3:...

从上面代码中我们可以看出两个问题

  • 尽管我们在

    forEach
    循环之前使用了
    await
    ,但是他不会等待
    forEach
    循环的执行,而是直接打印
    finished!

  • 三个

    getSomething()
    异步操作将是并发执行,请求时间短的操作将被率先打印,和请求顺序无关

参考文档

阮一峰 async函数
for 循环里的 await

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐