记一下,return并不能获取到异步函数的返回值

255 阅读2分钟

在编码过程中,为了满足业务需求,经常需要获取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 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。