前端处理异步回调操作用到的方法之一:Async/Await。可以说Async/Await是Promise的升级版,而且应用了Async/Await的异步请求的情况下,可以让代码看起来像同步方式调用解决异步回调。在ES7之前,了解到Promise是ES6为了解决异步回调而产生的解决方案,避免出现回调地狱(Callback Hell),那么ES7为什么又提出了新的Async/Await标准?问题答案就是:Promise虽然解决了异步嵌套的怪圈,使用表达清晰的链式表达;但是如果在实际开发过程中有些地方有大量的异步请求的时候,而且流程复杂嵌套的情况下,检查相关代码会发现一个比较尴尬。
Async/Await是基于Promise而来的,Async/Await是相互依存的,缺一不可,它们的出现就是为了Promise而来,也算是Promise的进化改良版,为的就是解决文章开始说的如果出现大量复杂嵌套不易读的Promise异步问题。
①Async/Await是基于Promise实现的,是写异步代码的新方式,它们不能用于普通的回调函数;
②Async/Await也是非阻塞的;
③Async/Await的写法使得异步代码看起来像同步代码,简洁、便于读取。
async必须声明的是一个function函数,await就必须是在async声明的函数内部使用,这是一个固定搭配,任何一种不符合这两个条件,程序就会报错,具体举实例来直观看一下:
let data = 'data'
a = async function () {
const b = function () {
await data
}
}
async是对generator的再一次语法糖封装,帮助实现了生成器的调用,使语句更贴近同步代码的表达方式,可以将async函数看做是多个异步操作封装的 promise对象。
async声明的函数的返回其实就是一个Promise,也就是说只要声明的函数是async,不管内部怎么处理,它返回的一定是一个Promise,举个例子如下所示:
(async function () {
return 'Promis+++‘
})() // 返回的是Promise+++
await的本质其实是可以提供等同于“同步效果”的等待异步返回能力的语法糖,也就是then的语法糖。如果想使用await来执行一个异步操作,那么其调用函数必须使用async来声明。
await能返回一个Promise对象,也能返回一个值。若await返回的是Promise对象,那么还可以继续给await的返回值使用then函数。举个实例看一下:
const a = async ()=>{
let message = '声明值111’
let result = await message;
console.log('由于上面的程序还没执行完,“等待一会”');
return result
}
a().then(result=>{
console.log('输出',result);
})
为什么说Async/Awaitd比Promise更胜一筹?具体原因如下所示。
根据上述关于Async/Awaitd的实例可以看到,Async/Awaitd的写法很简单,相比Promise的写法,不用写.then,不用写匿名函数处理Promise的resolve值,也不用定义多余的data变量,更避免了嵌套代码的操作,大大省去了很多代码行,使得处理异步操作的代码简洁明了,方便查阅和精准定位。
Async/Await可以让try/catch同时处理同步和异步的错误,而且在Promise中try/catch不能处理JSON.parse的错误,在Promise中需要使用.catch,但是错误处理的那坨代码会非常冗余,要知道实际开发过程中代码会比理论上的情况会更复杂。
通过使用Async/Await,try/catch能处理JSON.parse的错误,具体实例如下所示:
const request = async () => {
try {
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}
通过使用Async/Await,可以使得条件语句写法简洁又可以提高代码可读性,这里就不再举对比的例子,只举一个Async/Await的使用实例来说:
const request = async () => {
const data = await getJSON()
if (data.anotherRequest) {
const moreData = await anotherRequest(data);
console.log(moreData)
return moreData
} else {
console.log(data)
return data
}
}
在实际开发过程中会遇到这种场景:调用promise1,使用promise1返回的结果再去调用promise2,然后使用两者的结果去调用promise3。在没有使用Async/Await之前的写法,应该是这样的:
const request = () => {
eturn promise1()
.then(value1 => {
return promise2(value1)
.then(value2 => {
return promise3(value1, value2)
})
})
}
使用了Async/Await的写法之后,是这样的:
const request = async () => {
const value1 = await promise1()
const value2 = await promise2(value1)
return promise3(value1, value2)
}
通过上述两个写法,直观的看出来使用Async/Await之后会使得代码变得非常整洁简单,直观,高可读性。
如果实例中调用多个Promise,其中的一个Promise出现错误,Promise链中返回的错误栈没有显示具体的错误发生的位置信息,这就造成排查错误的耗时时长和解决的难度,甚至会起到反作用,假设错误栈的唯一函数名为errorPromise,但是它和错误没有直接关系。如果使用了Async/Await之后,错误栈会直接指向错误所在的函数,这样更清晰直观的方便排查问题所在,尤其是在查看分析错误日志的时候非常有效有用。
通过上面描述的Async/Await优点中,一直在反复强调Async/Await会使得代码简洁明了,其实在调试过程中,Async/Await也可以使得代码调试起来很轻松简单,相对于Promise来讲,不用再写太多箭头函数,可以直接像调试同步代码一样单步走,跳过await语句。
首先要明确知道,Promise自身是不能终止的,Promise本身只是一个状态机,存储了三种状态,一旦进行发出请求,就必须要闭环,无法进行取消操作,就算是在前面讲到的pending状态,也只是一个挂起请求的状态,但不是取消。
但是使用Async/Await的时候,想要终止程序就很简单,那是因为Async/Await语义化很明显,和一般的function的写法类似,想要终端程序的时候,直接return一个值(“”、null、false等)就可以了,实际上就是直接返回一个Promise。具体实例如下所示:
let count = 3;
const a = async ()=>{
const result = await delay(2000);
const result1 = await delaySecond(count);
if (count > 2) {
return '';
// return false;
// return null;
}
console.log(await delay(2000));
console.log(‘结束’);
};
a().then(result=>{
console.log(result);
})
.catch(err=>{
console.log(err);
})
async函数本质就是返回一个Promise。
Async/Await使用for循环获取数据(串行)
根据上面Promise的for循环获取数据来做对比,直接使用上述实例的场景,来看看Async/Await的写法,具体操作如下所示:
(async ()=>{
array = [timeout(2000), timeout(1000), timeout(1000)]
for (var i=0; i < array.length; i++) {
result = await array[i]();
console.log(result);
}
})()
通过对比,在这里还要夸一下Async/Await,直观的可以看到同样的需求,使用Async/Await来实现是不是非常的方便和简洁。
虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await
Async实际上是一个封装了自动化执行并返回一个Promise的Generator函数的语法糖。这句话的意思我们可以分为三个部分来解读:首先它有一个自动化执行,Generator函数是依靠不停的调用.net来依次执行的,Async有一个自动化执行的过程
Node.js7.6起, Node.js 搭载了有async函数功能的V8引擎。当Node.js 8于10月31日成为LTS版本后,我们没有理由不使用async函数。接下来,我将简要介绍async函数,以及如何改变我们编写Node.js应用程序的方式。
自2015年11 发布1.7版以来,TypeScript 已支持 async/await 关键字。编译器使用 yield 将异步函数转换为生成器函数。这意味着咱们无法针对 ES3 或 ES5,因为生成器仅在 ES6 中引入的。
async/await 大家肯定都用过,在处理异步操作的时候真的是很方便。那今天主要讲一些在使用 async/await 时容易忽略和犯错的地方。上面的代码中,每一行都会 等待上一行的结果返回后才会执行。
有一个图片列表,我想要在图片onload成功之后获取加载成功的图片列表,图片资源加载为异步,我们使用ES7的async await方式实现,多张图片,是用for循环。
Async 和 Awaiit 是 Promise 的扩展,我们知道 JavaScript 是单线程的,使用 Promise 之后可以使异步操作的书写更简洁,而 Async 使 Promise 像同步操作
最近代码写着写着,我突然意识到一个问题——我们既然已经有了 Promise 和 then,为啥还需要 async 和 await?这不是脱裤子放屁吗?
如果让你手写async函数的实现,你是不是会觉得很复杂?这篇文章带你用20行搞定它的核心。经常有人说async函数是generator函数的语法糖,那么到底是怎么样一个糖呢?让我们来一层层的剥开它的糖衣。
async/await是ES7的写法,可以让非同步call back写法看起来像同步的顺序去执行。以下我们new一个Promise的class并return给一个function
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!