js之async和await
async/await 是一种编写异步代码的新方法,之前异步代码的方案是回调和 promise,但async/await建立在promise基础上。
async和await是ES7中与异步操作有关的关键字。
async
async function name([param[, param[, ... param]]]) { statements }
async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve()
封装成 Promise 对象。
async function testAsync() { return "hello async"; } let result = testAsync(); console.log(result) // Promise {<resolved>: "hello async"}
await 关键字仅在 async function 中有效。如果在 async function 函数体外使用 await ,会得到一个语法错误。
await
[return_value] = await expression;
expression: 一个 Promise 对象或者任何要等待的值。
await针对所跟不同表达式的处理方式:
Promise对象:await 会暂停执行,等待 Promise 对象 resolve(异步操作完成),然后恢复 async 函数的执行并返回解析值。
非Promise对象:直接返回对应的值。
function testAwait (x) { return new Promise(resolve => { setTimeout(() => { resolve(x); }, 2000); }); } async function helloAsync() { var x = await testAwait ("hello world"); console.log(x); } helloAsync (); // hello world
很多人以为await会一直等待之后的表达式执行完之后才会继续执行后面的代码,实际上await是一个让出线程的标志。
await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈(后面会详述)的代码。等本轮事件循环执行完了之后又会跳回到async函数中等待await后面表达式的返回值,
如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise放入promise队列(Promise的Job Queue)。
function testSometing() { console.log("执行testSometing"); return "testSometing"; } async function testAsync() { console.log("执行testAsync"); return Promise.resolve("hello async"); } async function test() { console.log("test start..."); const v1 = await testSometing();//关键点1 console.log(v1); const v2 = await testAsync(); console.log(v2); console.log(v1, v2); } test(); var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//关键点2 promise.then((val)=> console.log(val)); console.log("test end...")
执行结果:
test start...
执行testSometing
promise start..
test end...
testSometing
执行testAsync
promise
hello async
testSometing hello async
在testSomething前增加aync:
async function testSometing() { console.log("执行testSometing"); return "testSometing"; } async function testAsync() { console.log("执行testAsync"); return Promise.resolve("hello async"); } async function test() { console.log("test start..."); const v1 = await testSometing();//关键点1 console.log(v1); const v2 = await testAsync(); console.log(v2); console.log(v1, v2); } test(); var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//关键点2 promise.then((val)=> console.log(val)); console.log("test end...") ///////////////////////////////////// test start... 执行testSometing promise start.. test end... promise testSometing 执行testAsync hello async testSometing hello async
和上一个例子比较发现promise.then((val)=> console.log(val));
先与console.log(v1);
执行了,原因是因为现在testSometing函数加了async,返回的是一个Promise对象要等它resolve,
所以将当前Promise推入队列,所以会继续跳出test函数执行后续代码。之后就开始执行promise的任务队列了,所以先执行了promise.then((val)=> console.log(val));
因为这个Promise对象先推入队列。