async/await被称作为异步最终的写法
- async function 关键字用来在表达式中定义异步函数。当然,你也可以用 异步函数语句 来定义。
- async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例
- AsyncFunction 构造函数用来创建新的 异步函数 对象,JavaScript 中每个异步函数都是 AsyncFunction 的对象。
async的基本语法
async function getdata (params) {
return 'hllo Nodejs'
}
//等价于
function getdata () {
return Promise.resolve('hllo Nodejs')
}
async function fooAsync () {
await 1
}
//等价于
function fooAsync () {
return Promise.resolve(1).then((data) => console.log(data))
}
在await表达式之后的代码可以被认为是存在在链式调用的then回调中,多个await表达式都将加入链式调用的then回调中,返回值将作为最后一个then回调的返回值。
了解 await 同步执行
async function foo() {
const result1 = await new Promise((resolve) => resolve('1'))
const result2 = await new Promise((resolve) => resolve('2'))
}
foo()
foo 函数调用时会返回一个Promise,但是这个Promise没有任何的返回参数,里面有二个Promise,第一个行会马上执行,第二行会等会等待到第一行执行完成后才会执行第二行
稍加改造
在原有的函数上面添加一个setTimeout函数,过5S后返回成功,
async function foo() {
const result1 = await new Promise((resolve) =>
{
console.log('result1函数');
setTimeout(() => resolve("1"), 5000)
}
);
const result2 = await new Promise((resolve, reject) => {
console.log(123);
setTimeout(() => resolve("2"));
});
return { result1, result2 };
}
console.time();
foo().then((data) => {
console.log(data);
console.timeEnd();
});sole.timeEnd();
});
最后代码执行事件为 5.012s
输出顺序为
result1函数
123
{ result1: '1', result2: '2' }
default: 5.012s
可见第一个Promise执行完成后才执行的第二个Promise,但是这里面要注意错误处理,使用catch 来捕获错误,否则会抛出异常
async function foo() {
const result1 = await new Promise((resolve) => setTimeout(() => resolve("1"), 2000) );
const result2 = await new Promise((resolve, reject) =>
setTimeout(() => resolve("2"));
);
return Promise.allSettled([await result1, await result2]);
}
foo().then((data) => {
console.log(data);
}).catch((err) => {
console.log(err);
});
由于 result2 抛出了异常,我们catch中能够捕获异常,
当async 返回一个数组的时候 我们第用then 时,其实内部是使用Promise.all()方法来执行,该返回的值是一个可迭代的数组,全部成功才返回成功,一个失败所有的都失败,
async function foo() {
const result1 = await new Promise((resolve) => {
setTimeout(() => resolve({ name: "selfsummer" }), 2000);
});
const result2 = await new Promise((resolve, reject) => setTimeout(() => resolve({ name: "自夏" })));
return [result1, result2];
}
foo().then((data) => {
Array.isArray(data) // true
console.log(data); //[ { name: 'selfsummer' }, { name: '自夏' } ]
})
.catch((err) => {
console.log(err);
});
使用catch捕获错误
async function foo() {
const result1 = await new Promise((resolve) => setTimeout(() => resolve({ name: "selfsummer" }), 2000));
const result2 = new Promise((resolve, reject) =>setTimeout(() => resolve({ name: "自夏" })));
const result3 = await new Promise((resolve, reject) => {
setTimeout(() => reject("1231232"));
});
return [await result1, await result2,result3];
}
foo().then((data) => {
console.log(data);
}).catch((err) => {
console.log(err); //1231232
});
并行执行await
var p1 = function () {
return new Promise((resolve) => {
setTimeout(() => {
resolve("2S");
}, 2000);
});
};
var p2 = function () {
return new Promise((resolve) => {
setTimeout(() => {
resolve("1S");
}, 1000);
});
};
var implement = async function () {
console.time();
const slow = await p1();
console.log(slow); // 2s
const fast = await p2();
console.log(fast); // 1s
console.timeEnd(); // 3.009s
};
implement();
上面我们创建了 二个函数 一个是 p1 一个是p2 在 implement 函数中执行,我们上面测试了,同时我们也知道,js 是一行一行执行的,上面p1函数的在2S后执行,下面我们来理解这个函数的执行过程
await将会等待promise的结束,等待时 implement 会把函数控制权给p1,当 await 表达式的 promise状态为fulfilled 时 并将控制权交还给调用implement 的函数。过了2S后p1执行完成,p1控制权将重新回到implement 函数内 成功后 await t表达式会赋值给左边即slow变量。接下来函数会继续进行,到达第二个await区域,此时foo函数的进程将再次被暂停,再把控制权给p2 等1s后 (promise状态为fulfilled) 作为结果返回给await表达式的左边即fast
还是上面的代码
var implement = async function () {
console.time();
const slow = p1();
const fast = p2();
await slow
await fast
console.timeEnd(); // 2.002s
};
implement();
同样代码只是调用方式不一样,执行的时间也不一样,为上面呢
两个计时器被同时创建,然后执行await。这两个计时器同时运行,这意味着程序完成运行只需要2秒,而不是3秒,即最慢的计时器的时间。
但是 await 仍是要等到Promise执行完后才会往下面执行,第二个 await 还是得等待第一个执行完,才会执行
如果要同时执行还是要使用 all ,race,allSettled,any 这几个方法