首页 > 技术文章 > JS异步编程

wujiaqi 2019-08-12 16:11 原文

Promise

const fs = require('fs');

new Promise(function(resolve, reject){
    fs.readFile('a.txt', {encoding: 'utf8'}, function(err, newData){
        if(err) reject('fail');
        console.log('dataA is %d', newData);

        resolve(newData);
    });
}).then(function(data){
    // 返回一个新的 promise 对象,使得下一个回调函数会等待该异步操作完成
    return new Promise(function(resolve, reject){
        fs.readFile('b.txt', {encoding: 'utf8'}, function(err, newData){
            if(err) reject('fail');
            console.log('dataB is %d', newData);

            resolve(parseInt(data)+parseInt(newData));
        });
    });
}).then(function(data){
    return new Promise(function(resolve, reject){
        fs.readFile('c.txt', {encoding: 'utf8'}, function(err, newData){
            if(err) reject('fail');
            console.log('dataC is %d', newData);

            resolve(parseInt(data)+parseInt(newData));
        });
    });
}).then(function(data){
    console.log('sum is %d', parseInt(data));
}).catch(function(err){
    throw Error('fail');
});

// $ node index.js
// dataA is 1
// dataB is 2
// dataC is 3
// sum is 6

Generator

const fs = require('fs');

const getData = function(fileName){
    return new Promise(function(resolve, reject){
        fs.readFile(fileName, {encoding: 'utf8'}, function(err, data){
            if(err) throw Error('fail');
            resolve(data);
        })
    });
}

const g = function* (){
    try{
        let dataA = yield getData('a.txt');  // yield 在暂停时刻并没有赋值,dataA 的值是在重新执行时刻由 next 方法的参数传入的
        console.log('dataA is %d', dataA);  
        let dataB = yield getData('b.txt');  
        console.log('dataB is %d', dataB); 
        let dataC = yield getData('c.txt');
        console.log('dataC is %d', dataC);

        console.log('sum is %d', parseInt(dataA) + parseInt(dataB) + parseInt(dataC));
    }catch(err){
        console.log(err);
    }
};

// 驱动 Generator 执行
function run (generator) {
    let it = generator();

    function go(result) {
        // 判断是否遍历完成,标志位 result.done 为 true 表示遍历完成
        if (result.done) return result.value;
        // result.value 即为返回的 promise 对象
        return result.value.then(function (value) {
            return go(it.next(value));
        }, function (error) {
            return go(it.throw(error));
        });
    }

    go(it.next());
}

run(g);

// $ node index.js
// dataA is 1
// dataB is 2
// dataC is 3
// sum is 6

Async/Await

const fs = require('fs');

// 封装成 await 语句期望的 promise 对象
const readFile = function(){
    let args = arguments;
    return new Promise(function(resolve, reject){
        fs.readFile(...args, function(err, data){
            // await 会吸收 resolve 传入的值作为返回值赋给变量
            resolve(data);
        })
    })
};

const asyncReadFile = async function(){
    let dataA = await readFile('a.txt', {encoding: 'utf8'});
    console.log('dataA is %d', dataA);
    let dataB = await readFile('b.txt', {encoding: 'utf8'});
    console.log('dataB is %d', dataB);
    let dataC = await readFile('c.txt', {encoding: 'utf8'});
    console.log('dataC is %d', dataC);
    console.log('sum is %d', parseInt(dataA) + parseInt(dataB) + parseInt(dataC));
};

asyncReadFile();
console.log('异步执行');

// $ node index.js
// 异步执行
// dataA is 1
// dataB is 2
// dataC is 3
// sum is 6

 

推荐阅读