co 实现 Generator 自动执行器

961 阅读1分钟

co运用

1. 基于thunk函数的执行

Step 1: 准备工作

./name.txt
    xiangju
./age.txt
    18

let { readFile } = require("fs"),
    { resolve } = require("path");
    
let readFileThunk = filename => callback => readFile(resolve(__dirname, filename), callback);

let gen = function* () {
    let f1 = yield readFileThunk("./name.txt"),
        f2 = yield readFileThunk("./age.txt");
    console.log(f1.toString());
    console.log(f2.toString());
}

Step 2.1: 手动执行上述 generator函数

let g = gen();
g.next().value((err, data) => {
    if (err) throw err;
    g.next(data).value((err, data) => {
        if (err) throw err;
        g.next(data);
    })
})

Step 2.2: 自动执行上述 generator函数

function run(gen) {
    let g = gen();
    
    function next(err = undefined, data = undefined) {  // next函数为thunk的callback
        if (err) throw err;
        let result = g.next(data);
        if (result.done) return result.value;  // 返回generator函数中return的返回值
        result.value(next);
    }
    
    next();
}
run(gen);

// xaingju
// 18

2. 基于Promise对象的执行

Step 1: 准备工作

./name.txt
    xiangju
./age.txt
    18

let { readFile } = require("fs"),
    { resolve: resolvePath } = require("path");
// 为避免resolve和下面的Promise回调里的resolve重名,改为resolvePath
    
let readFilePromise = filename => new Promise((resolve, reject) => {
    readFile(resolvePath(__dirname, filename), (err, data) => {
        if (err) return reject(err);
        resolve(data);
    })
})

let gen = function* () {
    let f1 = yield readFilePromise("./name.txt"),
        f2 = yield readFilePromise("./age.txt");
    console.log(f1.toString());
    console.log(f2.toString());
}

Step 2.1: 手动执行上述 generator函数

let g = gen();
g.next().value.then(data => g.next(data).value.then(data => g.next(data)));

Step 2.2: 自动执行上述 generator函数

function run(gen) {
    let g = gen();
    
    function next(data = undefined) {  // next函数为Promise resolve传入的value值
        let result = g.next(data);
        if (result.done) return result.value;  // 返回generator函数中return的返回值
        result.value.then(data => next(data);
    }
    
    next();
}
run(gen);

// xiangju
// 18