async await -- js异步最终解决方案
在 JS 中说到异步,我们肯定能想到最简单的异步方式–回调,和在 Promise 规范;这里,我们就不在说什么函数的回调了,直接说 Promise ,让我们回顾一下 Promise :如果对 Promise 不了解,请自行百度,或者看我的另一篇博客:ES6中的Promis的使用方法1. Promise简介这里我们就再啰嗦的介绍一下 Promise 对象Promise 对象用于表示一个异步操...
在 JS 中说到异步,我们肯定能想到最简单的异步方式–回调,和在 Promise 规范;这里,我们就不在说什么函数的回调了,直接说 Promise ,让我们回顾一下 Promise :
如果对 Promise 不了解,请自行百度,或者看我的另一篇博客:ES6中的Promis的使用方法
1. Promise简介
这里我们就再啰嗦的介绍一下 Promise 对象
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。
Promise 对象是由关键字 new 及其构造函数来创建的。构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数 resolve 和 reject 作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数,而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用 reject 函数。
Promise 状态:
- pending:初始状态,既不是成功,也不是失败状态
- fulfilled:操作成功
- rejected:操作失败
让我们看一个 Promise 的例子:
function division(fdiv, div) {
return new Promise(function(resolve, reject) {
// 使用延时函数,模拟异步
setTimeout(() => {
if(div === 0) {
// 模拟异常
reject('0不能作为除数!!!')
} else {
// 模拟正常
resolve(fdiv / div);
}
}, 5000);
});
}
var pms = division(100, 10);
pms.then(res => {
console.log(res);
// 10
}).catch(err => {
console.log(err);
})
console.log(pms);
// Promise {<resolved>: 10}
通过 then 传递执行成功和失败的方法,或者统一使用 catch 单独捕捉失败;并且 then 支持链式反映,可以无限连接then ,但是上一个 then 必须要返回Promise 对象,并且可以使用 catch 统一捕获异常。
2. 如何理解async、await
async 即“异步”,而 await 为“等待”;这样就很好理解了,async 用来声明一个异步操作的方法(async function 方法名),而 await 用于等待一个异步任务执行完成。
这里需要注意:await 只能出现在 async 函数中
让我们修改一项上面的demo,使用 async 和 await 完成吧:
function division(fdiv, div) {
return new Promise(function(resolve, reject) {
// 使用延时函数,模拟异步
setTimeout(() => {
if(div === 0) {
// 模拟异常
reject('0不能作为除数!!!')
} else {
// 模拟正常
resolve(fdiv / div);
}
}, 5000);
});
}
async function test(x, y) {
try {
const rtn = await division(x, y);
console.log(rtn);
} catch(e) {
// 经过测试,我们可以发现,当走异常的时候,我们可以使用try...catch...进行异常捕捉
console.log(e);
}
}
test(100, 10); // 10 在try中打印
test(100, 0); // 0不能作为除数!!! 在catch中打印
3. async、await如何执行
async 声明方法为异步操作,await 是一个操作符,即 await 后面是一个表达式。
async 的返回值:
async function test(fdiv, div) {
if(div === 0) {
throw "0不能为除数!!!";
} else {
return fdiv / div
}
}
console.log(test(100, 10));
// Promise {<resolved>: 10}
console.log(test(100, 0));
// Promise {<rejected>: "0不能为除数!!!"}
// Uncaught (in promise) 0不能为除数!!!
从上面可以看出,当调用一个 async 函数时,会返回一个 Promise 对象。根据mdn的解释:
- 当这个
async函数返回一个值时,Promise的resolve方法会负责传递这个值; - 当
async函数抛出异常时,Promise的reject方法也会传递这个异常值。async函数中可能会有await表达式,await表达式会使async函数暂停执行,直到表达式中的Promise解析完成后继续执行async中await后面的代码并返回解决结果。
注意: await 关键字仅仅在 async function中有效
既然返回的是 Promise 对象,那么如果在外层不能使用 await 关键字获取的情况下,我们就可以使用 then 链来处理解过了:
async function test(fdiv, div) {
if(div === 0) {
throw "0不能为除数!!!";
} else {
return fdiv / div
}
}
// 使用then链处理结果
test(100, 10).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
那么如果 async 函数没有返回值,又会怎么样呢;这个很容一想到,因为方法没有返回值得时候,如果声明变量接受,则接收到的值为 undefined;所以他会返回:Promise.resolve(undefined)
既然 async 和 `` 基本上和 Promise 相似,但是他们有没有区别呢;这里还是有一点区别的,如下:
function division(fdiv, div) {
return new Promise(function(resolve, reject) {
// 使用延时函数,模拟异步
setTimeout(() => {
if(div === 0) {
// 模拟异常
reject('0不能作为除数!!!')
} else {
// 模拟正常
resolve(fdiv / div);
}
}, 5000);
});
}
// 使用await方式实现
async function test1() {
const t = await division(100, 10);
console.log(t);
// 这句代码必须等待await执行完成后,才能执行
console.log("执行这句话")
}
// 使用Promise方式实现
function test2() {
division(100, 10).then(res => {
console.log(res);
});
// 这句代码不用等到then执行完成,就还立刻执行
console.log("执行这句话")
}
test1();
test2();
区别就是这样的,大家根据场景的不同,进行选择使用吧!
4. await 操作符
MDN 是这样描述 await 的:
await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行async function。若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。
起始简单说就是:
async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
按照mdn解释 await 会暂停当前 async 函数执行,并且 await 后面是一个表达式,即这个 await 等待的是一个表达式(这个表达式返回promise 对象或者一个具体的值):
- 假如这个表达式如果返回的是一个
Promise对象, 那么它的返回值,实际上就是Promise的回调函数 resolve 的参数,如果这个Promise rejected了,await表达式会把Promise的异常抛出。 - 假如这个表达式如果返回的是一个常量,那么会把这个常量转为
Promise.resolve(xx),同理如果没有返回值也是Promise.resolve(underfind)
这里不在列举更多的例子,上面的例子已经包含了,我想表达的一切。
5. 总结
async用来声明方法是异步方法awiat用于async方法之中,用来暂停方法的执行,等待后面表达式给出结果,然后继续执行方法async函数的返回结果为一个Promise对象;当async函数返回一个值的时候,就等于Promise调用resolve函数;当async函数抛出异常的时候,就等于Promise调用reject函数。await操作符用于等待一个Promise对象,并将Promise的结果进行转换(成功则将其resolve中的结果作为返回值,失败则抛出异常,将reject中的值作为异常信息);如果await后面不是Promise对象,则会被转换为Promise.resolve(xx)
更多推荐


所有评论(0)