Async & generator & Promise

shirleyR發表於2019-04-08

redux-saga中大量涉及到Es6的generator語法,於是乎將generator/promise/async之間的關聯和區別複習一下。這些語法糖的出現無外乎是為了簡化深度回撥,寫法的簡化,程式碼的方便閱讀。

generator

generator迭代器語法中涉及的語法糖*和yield。 *用在生成器函式的開頭。

// a simple generator function
function* gen() {
    yield 1;
    yield 2;
    yield *[3,4,5];
}
var res = gen();
res.next(); // {value: 1, done: false}
for(var value of gen()) {
    console.log(value);
}
// result is 1,2,3,4,5
複製程式碼

generator的yield語法返回一個物件{value: val, done: false/true},generator函式相對於迭代器,next指向下一個yield。generator的yield後面可以放同步和非同步操作。

await/async

Promise是鏈式的then來完成每個task。而await/async的出現使得非同步的操作在寫法上和同步一樣,並且每個await時間只能處理一個非同步操作。

async function init() {
    await doTask1();
    await doTask2();
    await doTask3();
}
// an implementation using a generator function
function* init() {
    yield doTask1();
    yield doTask2();
    yield doTask3();
}
// execute generator function
function runner(genFn) {
    const itr = genFn();
    function run(arg) {
        const result = itr.next(arg);
        if (result.done) {
            return result.value;
        } else {
            return Promise.resolve(result.value).then(run);
        }
    }
    return run();
}
複製程式碼

async/await可以使用Promise加generator來實現。

async function foo() {
    await bar();
}
// babel 的編譯結果
// https://hackernoon.com/async-await-generators-promises-51f1a6ceede2
let foo = (() => {
    var _ref = _asyncToGenerator(function* () {
        yield doTask1();
    });
    return function foo() {
        return _ref.apply(this, arguments);
    }
})();

function _asyncToGenerator(fn) {
    return () => {
        var gen = fn.apply(this, arguments);
        return new Promise((resolve, reject) =>{
            function step(key, arg) {
                try {
                    var info = gen[key](arg);
                    var value = info.value;
                } catch(error) {
                    reject(error);
                    return;
                }
                if (info.done) {
                    resolve(value);
                } else {
                    return Promise.resolve(value).then((value => {
                        step("next", value);
                    }, (err) => {
                        step("throw", err);
                    }));
                }
            }
            return step("next");
        })
    }
}

複製程式碼

Promise Vs Async

v8 fast async

Promise:

function handler() {
    return validateParams()
        .then(dbQuery)
        .then(serviceCall)
        .then(result => {
            return result;
        })
}
複製程式碼

async 函式

async function handler() {
    await validateParams();
    const dbResults = await dbQuery();
    const results = await serviceCall(dbResults);
    return results;
}
複製程式碼

v8 fast async

Event loop

Javascript是單執行緒執行,非同步操作都是通過事件來處理的。 待續。。。

相關文章