导语: 异步编程的最高境界就是不关心它是否是异步. async,await 很好的解决了这一点, 将异步强行转换为同步处理.
async/await 与 promise 不存在谁代替谁的说法, 因为 async/await 是寄生于 Promise, 是 Generater 的语法糖.
温馨提示: 如果你已经知道了关于 async await 的基本用法, 请直接看分割线以下内容
Generator
1. 调用 Generator 函数, 返回一个遍历器对象, 代表 Generator 函数的内部指针.
2. 以后, 每次调用遍历器对象的 next 方法, 就会返回一个有着 value 和 done 两个属性的对象.
3. value 属性表示当前的内部状态的值, 是 yield 表达式后面那个表达式的值; done 属性是一个布尔值, 表示是否遍历结束.
- function* helloWorld () {
- yield 'hello'
- yield 'world'
- return 'ending'
- }
- var hw = helloWorld()
- console.log(hw) // helloWorld {<suspended>}
- console.log(hw.next()) // {value: "hello", done: false}
- console.log(hw.next()) // {value: "world", done: false}
- console.log(hw.next()) // {value: "world", done: false}
- console.log(hw.next()) // {value: undefined, done: true}
- async
1. async 其实就是对 Generator 的封装, 只不过 async 可以自动执行 next().
2. async 必须等到里面所有的 await 执行完, async 才开始 return, 返回的 Promise 状态才改变. 除非遇到 return 和错误.
3. async 默认返回一个 Promise, 如果 return 不是一个 Promise 对象, 就会被转为立即 resolve 的 Promise, 可以在 then 函数中获取返回值.
- async function fn () {
- await 100
- await 200
- return 300
- }
- fn().then(res => {
- console.log(res) // 300
- })
再看下面这个例子:
打印结果如下:(返回的是 promise 对象)
如果在 async 函数中抛出了错误, 则终止错误结果, 不会继续向下执行:
如果希望一个 await 失败, 后面的继续执行, 可以使用 try...catch 或者在 await 后面的 Promise 跟一个 catch 方法:
- async function f() {
- try {
- await Promise.reject('出错了');
- } catch(e) {
- }
- return await Promise.resolve('hello world');
- }
- f()
- .then(v => console.log(v)) // hello world
- // catch
- async function f() {
- await Promise.reject('出错了')
- .catch(e => console.log(e)); // 出错了
- return await Promise.resolve('hello world');
- }
- f()
- .then(v => console.log(v)) // hello world
================================ 分割线 ==================================
面试题
[例 1]
- async function async1() {
- console.log("async1 start");
- await async2();
- console.log("async1 end");
- return 'async return';
- }
- async function async2() {
- console.log("async2");
- }
- console.log("script start");
- setTimeout(function() {
- console.log("setTimeout");
- }, 0);
- async1().then(function (message) { console.log(message) });
- new Promise(function(resolve) {
- console.log("promise1");
- resolve();
- }).then(function() {
- console.log("promise2");
- });
- console.log("script end");
输出顺序如下:
[分析]:
1. 首先我们从上到下看, 打印: script start;
2. setTimeout 虽然是 0, 但依然要放到执行栈, 等待后续执行. 继续往下走;
3. async1 开始执行, 当函数里遇到 await 时, 暂停执行 (await 所在行放在本次执行完), 执行完后遇到 then 是异步, 此时 async1 被添加到任务队列;
4. new Promise() 实例对象被 new 出来后, 它里面的 promise1 会立刻打印, 然后又遇到 then, 此时 promise 对象被添加到任务队列;
[例 2] :
- var p = new Promise((res,rej) => {
- res('hello one')
- console.log('good morning')
- })
- function hello() {
- console.log('hello begins')
- return p
- }
- hello().then(res => {
- console.log(res)
- console.log('hello1111111111')
- return 'hello two'
- }).then(res => {
- console.log(res)
- console.log('hello22222222222')
- return 'hello three'
- }).then(res => {
- console.log(res)
- console.log('hello33333333333')
- })
- function test1 () {
- console.log('test1')
- }
- async function asy () {
- console.log('asy begins')
- await console.log('asy---111111')
- console.log('async1')
- await console.log('asy---222222')
- console.log('asy ends')
- }
- asy()
- test1()
- function* gnrt () {
- console.log(1)
- yield console.log(11111111)
- console.log(2)
- yield console.log(22222222)
- console.log(3)
- yield console.log(33333333)
- }
- var result = gnrt()
- result.next()
- result.next()
- result.next()
输出顺序如下:
来源: http://www.bubuko.com/infodetail-3329281.html