使用
对比普通函数,注意打印顺序,addB函数先打印,addA后打印,结果也不一样。
function promise() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(3)
})
})
}
async function addA() {
var re = await promis();
console.log(re)
}
function addB() {
var re = promis();
console.log(re)
}
addA()
addB()
var promis = function() {
return Promise.resolve(3)
}
async function add() {
var re = await promis()
}
add().then(function(res) {
console.log(res) // undefined
}).then((res) => {
console.log(res) // undefined
}).then((res) => {
console.log(res) // undefined
})
函数没有返回值,调用后可以无限的调用then函数,结果是undefined。因为async函数的返回值是promise,而promise函数的then函数默认return 了一个新的promise,所以这里可以实现链式调用。
给函数加一个返回值,打印结果发生了改变,返回值可以在then函数中拿到。
async function add() {
var re = await promis();
return re
}
add().then(function(res) {
console.log(res) // 3
}).then((res) => {
console.log(res) // undefined
}).then((res) => {
console.log(res) // undefined
})
处理异常,虽然async函数也可以捕获异常,但是,如果异步请求异常了,async函数内部await下面的内容不会再执行了。
function promise() {
return new Promise((resolve) => {
setTimeout(() => {
console.log(nam)
resolve(3)
})
})
}
async function addB() {
var re = promis();
console.log(4) // 这里无法执行
}
addB().then().catch(function() {
console.log(5) // 这里可以执行
})
使用try catch解决上面问题:
async function addB() {
try {
var re = promis();
} catch (error) {
console.log(error) //这里可以执行
}
console.log(4) // 这里可以执行
}
addB().then().catch(function() {
console.log(5) // 这里不执行
})
实现一个简单的async/await
如上,我们掌握了Generator函数的使用方法。async/await语法糖就是使用Generator函数+自动执行器来运作的,返回值是一个 promise。 如果想进异步了解Generator函数+自动执行器,可以移步《Generator函数的使用和原理》
es6新增的Generator函数是用来解决异步问题的,那为什么不直接使用Generator函数呢?是因为Generator函数不能直接执行,需要手动调用,或者结合自动执行器来使用。而async/await函数内部自带了自动执行器,使用起来方便,美观。
// async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已
// async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
// Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器和普通函数一样执行
// async函数对 Generator 函数的改进:
/*
(1)内置执行器
(2)更好的语义
(3)更广的适用性
(4)返回值是 Promise
*/
// async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。
async function fn(args) {
// ...
}
// 等同于 里面的await 换成 yield
function fn(args) {
return spawn(function*() {
// ...
});
}
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch (e) {
return reject(e);
}
if (next.done) {
return resolve(next.value); // 这也是为什么 不使用try catch的话,异常异步请求后面的代码不再执行的原因,从这里不再继续调用nex()方法了。
}
Promise.resolve(next.value).then(function(v) {
step(function() {
return gen.next(v);
});
}, function(e) {
step(function() {
return gen.throw(e); // 这里可以解释为什么async 函数需要使用try catch来捕获异常,生成器函数的throw,会让代码到catch里面
});
});
}
step(function() {
return gen.next(undefined);
});
});
}