在编码过程中,为了满足业务需求,经常需要获取JS异步函数的返回值。
在刚开始写时,会按照普通函数的逻辑处理,但是发现在调用时并没有获取到正确的return值。
function getSomething() {
var r = 0;
setTimeout(function() {
r = 2;
}, 10);
return r;
}
function compute() {
var x = getSomething();
alert(x * 2);
}
compute(); //0 而非 4
解决方式一、Promise和async
function getSomething() {
var r = 0;
return new Promise(function(resolve) {
setTimeout(function() {
r = 2;
resolve(r);
},10)
})
}
async function compute() {
var x = await getSomething();
alert(x * 2);
}
compute();
解决方式二、Promise和generator
function getSomething() {
var r = 0;
return new Promise(function(resolve) {
setTimeout(function() {
r = 2;
resolve(r);
},10)
})
}
function *compute() {
var x = yield getSomething();
alert(x * 2);
}
var it = compute();
it.next().value.then(function(value) {
it.next(value);
})
异步编程的最高境界,就是根本不用关心它是不是异步。
关于async和generator
异步操作是 JavaScript 编程的麻烦事。
从最早的回调函数,到 Promise 对象,再到 Generator 函数,每次都有所改进,但又让人觉得不彻底。它们都有额外的复杂性,都需要理解抽象的底层运行机制。
async 函数就是 Generator 函数的语法糖。
async 函数的优点
async 函数对 Generator 函数的改进,体现在以下三点。
(1)内置执行器。 Generator 函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器。也就是说,async 函数的执行,与普通函数一模一样,只要一行。
(2)更好的语义。 async 和 await,比起 * 和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。
(3)更广的适用性。 co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。