Nodejs -- 异步编程

                                                                        Nodejs -- 异步编程

本文主要介绍一些偏基础和概念性的东西,尽量用简单的语言来阐明这些点,作为为Node做前提准备,同时也是知识整理。

1. 通常的语言是是不接受把方法直接作为参数的,当然在一些语言中也是会有变通的,入C#中有委托,代理,不过在JavaScript中是可以直接把方法(function)作为参数传入另一方法的这种方式,也就是咱们通常所说的高阶函数。如下:

var functionAsParam = function(){
    console.info("I am a param");
}
(function(functionAsParam){
    functionAsParam();
})()

2. JS中偏函数的用法,也就是利用apply,call等函数,如下:

var toString = Object.prototype.toString;
function type(obj){
    return function(param){
        var result = toString.call(obj);
        console.info("[object " + typeof(param) + "]" == result);
    }
}
var isString = type(String());
isString("qiang.c.chen");

        注意上面的例子有个额外的支持点闭包,函数执行的作用域不同而造成内部可以访问到外部的这种现象。换句话来说上面的functionType方法本来已经执行完毕,本应该会被销毁,但是因为它返回的是个方法(这也是JS的一个特点,可以把方法作为返回值,通常语言中是不行的),而这个方法又是单独的作用域,或者说有单独的存储空间,所以不会被销毁。

3. Node中事件的发布与订阅

callback回掉又称发布/订阅模式,Node自身提供的events模块是该模式的简单事件,它具有addListener/on(),once(),removeListerner(),removeAllListeners(),emit()等基本的事件监听模式的方法实现。操作简单如下:

订阅                                                                                        发布

emitter.on("event1", function(message){ })                             emitter.emit("event1", "I am a trigger")

可以为一个事件添加多个监听,同时监听器也可以灵活的添加和删除。

· Node中继承events模块如下:

var util = requuire('util');
var events = require("events");
function TestObj(){
    events.EventEmitter.call(this);
}
util.inherits(TestObj, events.EventEmitter);

4. Promise/Deferred模式,为了解决深度嵌套问题也就是所谓的“恶魔金字塔”,保持代码的整洁。在此基础上比较经典的封装解决掉了多异步协作,序列化执行的Promise,Promise化API等问题。

Promise 可以理解为是事件的监听+缓存。

Deffered 可以理解为延迟对象,也就是事件的触发与发布,这里是重点需要封装异步的调用,回调函数的注入。

// Promise
var Promise = function(){
    EventEmitter.call(this);
}
util.inherits(Promise, EventEmitter);
Promise.Prototype.then = function(successHandler, errorHandler, progressHandler){
    this.once('success', successHandler);
    this.once('error', errorHandler);
    this.once('progress', progressHandler);
    return this;
}

// Deferred 
var Deferred = function(){    
    this.state = '';
    this.promise = new Promise();
}
Deferred.prototype.resolve = function(obj){
    this.state = 'fulfilled';
    this.promise.emit('success', obj);
}
Deferred.prototype.reject = function(err){
    this.state =  'failed';
    this.promise.emit('error', err);
}
Deferred.prototype.progress = function(data){
    this.promise.emit('progress', err);
}

// API
var promisify = function(res){
    var deferred = new Deferred();
    var result = '';
    res.on('data', function(callbackResult){
        result += callbackResult;
        deferred.progress(chunk);
    });
    res.on('end', function(){
        promise.resolve(result);
    });
    res.on('error', function(err){
        promise.reject(err);
    });
    return deferred.promise;
}

// Invoke API
promisify(res).then(function(callbackResult){
    // do some logic
},
function(error){
    console.info(error);
},
function(){
})

以上为Promise/Deferred的基本原理,如在实际应用中直接用顺手封装完的库即可,例如when,Q等。

5. 流程控制,最知名的流程控制模块async,值得注意的是callback,这里的callback是由async通过函数注入进来的,而不是使用者指定的。

· 任务串行

async.series([
    function(callback){
        fs.readFile('file1.txt', 'utf-8', callback);
    },
    function(callback){
        fs.readFile('file2.txt', 'uft-8', callback);
    }],
    function(err, results){
        // todo error
    }
)

· 任务并行

sync.parallel([
    function(callback){
        fs.readFile('file1.txt', 'utf-8', callback);
    },
    function(callback){
        fs.readFile('file2.txt', 'utf-8', callback);
    }],
    function(err, results){    
        // todo error
    }
)

         · 异步调用的依赖处理

async.waterfall([
    function(callback){
        fs.readFile('file1.txt', 'utf-8', function(err, content){
            callback(err, content);
        });
    },
    function(arg1, callback){
        fs.readFile(arg1, 'utf-8', function(err, content){
            callback(err, content);
        });
    }],
    function(err, result){
        // todo err
    }
)

            同时对于复杂的业务逻辑可以使用auto(obj)方法,obj为一个可配置的对象。其他流程控制库Step,EventProxy,wind等,还有通过源代码编译的方式来实现流程控制。

猜你喜欢

转载自blog.csdn.net/castm/article/details/81093301