摘要:结果输出可以看出函数返回的是一个对象,如果函数中一个直接量,函数会封装成对象返回,而如果没有返回值时,函数会返回在没有结合时,函数会立即执行,返回一个对象。
JS中的异步操作从最初的回调函数演进到Promise,再到Generator,都是逐步的改进,而async函数的出现仿佛看到了异步方案的终点,用同步的方式写异步。
原文链接
async函数简单解释async函数就是Generator函数的语法糖。
Generator函数写法
let promise = function (val){ return new Promise(function (resolve, reject){ setTimeout(()=>{ console.log(val); resolve(val); },1000); }); }; let gen = function* (){ let p1 = yield promise("1"); let p2 = yield promise("2"); }; let genF = gen();
async函数写法
let promise = function (val){ return new Promise(function (resolve, reject){ setTimeout(()=>{ console.log(val); resolve(val); },1000); }); }; let gen = async function (){ let p1 = await promise("1"); let p2 = await promise("2"); };
async函数是在Generator函数上进行的改进,语法上Generator函数的星号换成了async,yield换成了await。
而async也与Generator函数不同:
自带内置执行器,Generator函数需要依靠执行器,而async可以和普通函数一样,只需要一行
相对Generator函数,async和await语义更清楚
适用性强,yield后只能是Thunk函数和Promise对象,而await后可以是Promise对象和原始类型的值(数值、字符串、布尔型等)
async作用寄予async函数的期望是希望可以帮助我们解决异步操作问题,所以需要搞清楚async函数的返回值是什么。
async function asyncAwait() { return "async await"; } let a = asyncAwait(); console.log(a);
结果输出:
Promise {: "async await"}
可以看出async函数返回的是一个Promise对象,如果函数中return一个直接量,async函数会封装成Promise对象返回,而如果没有返回值时,async函数会返回undefined
Promise {: undefined}
在没有结合await时,async函数会立即执行,返回一个Promise对象。
await等待await是个运算符,等待的结果是Promise对象或其他值,比如:
function func1() { return "async"; } async function func2() { return Promise.resolve("await"); } async function asyncAwait() { let f1 = await func1(); let f2 = await func2(); console.log(f1, f2); } asyncAwait()
结果输出:
async await
await表达式的运算取决于等待的结果,如果它等到的不是一个Promise对象,那运算结果就是它等到的东西,
而如果它等到的是一个Promise对象,它会阻塞后面的代码,等着Promise对象resolve,然后得到resolve的值,作为表达式的运算结果。
async函数调用会封装在Promise中,这也是await需要在async函数中使用的原因。
对于多个异步操作中,Promise的then可以解决多层回调问题。
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t) { console.log(`step1 in ${t}ms`); return ajax(t); } function step2(t) { console.log(`step2 in ${t}ms`); return ajax(t); } function step3(t) { console.log(`step3 in ${t}ms`); return ajax(t); } function submit(){ console.time("submit"); step1(200) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(result => { console.log(`result is ${result}ms`); console.timeEnd("submit"); }); } submit();
async函数实现:
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t) { console.log(`step1 in ${t}ms`); return ajax(t); } function step2(t) { console.log(`step2 in ${t}ms`); return ajax(t); } function step3(t) { console.log(`step3 in ${t}ms`); return ajax(t); } async function submit(){ console.time("submit"); const t1 = 200; const t2 = await step1(t1); const t3 = await step2(t2); const result = await step3(t3); console.log(`result is ${result}`); console.timeEnd("submit"); } submit();
结果输出:
step1 in 200ms step2 in 400ms step3 in 600ms result is 800 submit: 1209.85107421875ms
而如果需求变更,每一步的参数都是之前步骤的结果后,async函数可以写成:
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t1) { console.log(`step1 in ${t1}ms`); return ajax(t1); } function step2(t1, t2) { console.log(`step2 in ${t1}ms,${t2}ms`); return ajax(t1 + t2); } function step3(t1, t2, t3) { console.log(`step3 in ${t1}ms,${t2}ms,${t3}ms`); return ajax(t1 + t2 + t3); } async function submit(){ console.time("submit"); const t1 = 200; const t2 = await step1(t1); const t3 = await step2(t1, t2); const result = await step3(t1, t2, t3); console.log(`result is ${result}`); console.timeEnd("submit"); } submit();
结果输出:
step1 in 200ms step2 in 200ms,400ms step3 in 200ms,400ms,800ms result is 1600 submit: 2210.47998046875msasync/await注意点
async用来申明里面包裹的内容可以进行同步的方式执行,await则是进行执行顺序控制,每次执行一个await,阻塞代码执行等待await返回值,然后再执行之后的await。
await后面调用的函数需要返回一个promise。
await只能用在async函数之中,用在普通函数中会报错。
await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
async/await try/catch写法async function asyncAwait() { try { await promise(); } catch (err) { console.log(err); } } // 另一种写法 async function asyncAwait() { await promise().catch(function (err){ console.log(err); }); }总结
async/await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案,当你深入了解原理后会发现仿佛看到了异步回调隧道的尽头亮光。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/107304.html
摘要:以往的异步方法无外乎回调函数和。当然,对这个新特性也有一定的担心,体现在他使得异步代码变的不再明显,我们好不容易已经学会并习惯了使用回调函数或者来处理异步。 自从Node的7.6版本,已经默认支持async/await特性了。如果你还没有使用过他,或者对他的用法不太了解,这篇文章会告诉你为什么这个特性不容错过。本文辅以大量实例,相信你能很轻松的看懂,并了解Javascript处理异步的...
摘要:以往的异步方法无外乎回调函数和。当然,对这个新特性也有一定的担心,体现在他使得异步代码变的不再明显,我们好不容易已经学会并习惯了使用回调函数或者来处理异步。 自从Node的7.6版本,已经默认支持async/await特性了。如果你还没有使用过他,或者对他的用法不太了解,这篇文章会告诉你为什么这个特性不容错过。本文辅以大量实例,相信你能很轻松的看懂,并了解Javascript处理异步的...
摘要:以往的异步方法无外乎回调函数和。出错了出错了总结接口遍历器对象除了具有方法,还可以具有方法和方法。函数调用函数,返回一个遍历器对象,代表函数的内部指针。 引言 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术。 在异步编程中,还有一种常用的解决方案,它就是Generator生成器函数。顾...
摘要:回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。同步方式请求异步同步请求当请求开始发送时,浏览器事件线程通知主线程,让线程发送数据请求,主线程收到 一直以来都知道JavaScript是一门单线程语言,在笔试过程中不断的遇到一些输出结果的问题,考量的是对异步编程掌握情况。一般被问到异步的时候脑子里第一反应就是Ajax,setTimse...
阅读 761·2021-11-18 10:02
阅读 2418·2021-11-11 16:54
阅读 2706·2021-09-02 09:45
阅读 625·2019-08-30 12:52
阅读 2629·2019-08-29 14:04
阅读 2709·2019-08-29 12:39
阅读 405·2019-08-29 12:27
阅读 1867·2019-08-26 13:23