async与await
消除回调
虽然我们有了Promise的规范,异步任务有统一的处理方式。
但是你会发现,其实现在有异步的情况,我们的代码还是不好写。
但是有了统一的处理方式,ES官方就可以对其进一步优化
ES7推出了两个重要的关键字async
和await
,用于更加优雅的表达Promise
async
async关键字用于修饰函数,被它修饰的函数,一定返回Promise
async function method1(){
return 1; // 该函数的返回值是Promise完成后的数据
}
method1(); // Promise { 1 }
async function method2(){
return Promise.resolve(1); // 若返回的是Promise,则method得到的Promise状态和其一致
}
method2(); // Promise { 1 }
async function method3(){
throw new Error(1); // 若执行过程报错,则任务是rejected
}
method3(); // Promise { <rejected> Error(1) }
await
await
关键字表示等待某个Promise完成,它必须用于async
函数中
async function method(){
const n = await Promise.resolve(1);
console.log(n); // 1
}
// 上面的函数等同于
function method(){
return new Promise((resolve, reject)=>{
Promise.resolve(1).then(n=>{
console.log(n);
resolve(1)
})
})
}
要注意思考上面的问题: 为什么必须要把await放在一个async的函数中? 其实给我们的感觉
const n = await Promise.resolve(1);
console.log(n); // 1
这两句代码是分开的,实际上,这还是ES7给我们的一个语法糖,把await等代码包裹在一个async封装的函数中,其实就是放在then的回调函数中,就算我们在下面多写一些代码,这些代码也都是放在then的回调函数中的
思考:下面两段代码的打印结果是什么?并且解释一下为什么?
async function method(){
const n = await Promise.resolve(1);
console.log(n);
console.log("hello");
}
method();
console.log("world")
async function method(){
console.log("hello");
const n = await Promise.resolve(1);
console.log(n);
}
method();
console.log("world")
await
也可以等待其他数据
async function method(){
const n = await 1; // 等同于 await Promise.resolve(1)
}
如果需要针对失败的任务进行处理,可以使用try-catch
语法
async function method(){
try{
const n = await Promise.reject(123); // 这句代码将抛出异常
console.log('成功', n)
}
catch(err){
console.log('失败', err)
}
}
method(); // 输出: 失败 123
简单来说,有了await
和async
这两个关键字之后,以后我们调用异步代码,就可以像调用同步代码一样去调用,而不用去纠结调用异步函数的时候,值到底存不存在,比如之前的ajax代码:
const ajaxPromise = param => {
return new Promise((resovle, reject) => {
var xhr = new XMLHttpRequest();
xhr.open(param.type || "get", param.url, true);
xhr.send(param.data || null);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
resovle(JSON.parse(xhr.responseText));
} else{
reject(JSON.parse(xhr.responseText));
}
}
}
})
}
这是我们封装的ajaxPromise
函数,我们现在可以这样调用:
async function test(){
let data = await ajaxPromise({
url:"/users",
})
console.log(data);
setHTML(data);
}
test();
就像获取一般函数的返回值一样去使用他即可。
这样子的话,我们再回到之前找工作的那个问题上,之前困扰我们的是,我们只有等着上一家的回复之后,才能继续在回调函数中写代码,但是现在有了await
与async
就完全解决了我们的问题,我们甚至可以像同步代码一样,直接写个循环就行了
async function test() {
let companies = ["华为", "小米", "京东", "天美"];
try { //如果是reject状态,直接try...catch...捕获异常原因
//循环公司名称,依次发送简历
for (let i = 0; i < companies.length; i++) {
let d = await sendMessage(companies[i]);
if (d.pass) { //如果简历通过直接退出循环
console.log(d.msg);
break;
}
else {
console.log(d.msg);
}
}
} catch (e) {
console.log(e);
}
}
test();
Comments