让nodejs方法同时支持async/await和回调模式调用

使用async/await可以让你用同步的方式写代码,忘掉callback,简直不能更爽,但是原来的老接口不支持async/await调用怎么办呢?

我琢磨出下面一个方法,根据最后一个参数是否是function类型的参数,来判断是哪种调用,而且做到可以无痛改造原有方法。

function promisify (func, this_obj) {//(from http://yoyo.play175.com)
    return function() {
        if (arguments.length > 0 && arguments[arguments.length - 1].constructor == Function) {
            //回调模式
            func.apply(this_obj, arguments);
        } else {
            //否则是Promise或者async/await模式
            let args = arguments;
            return new Promise((resolve, reject) => {
                Array.prototype.push.call(args, function(err, ret) {
                    if (err) {
                        //有错误产生
                        reject.call(this_obj, err);
                    } else {
                        //没有错误产生,去掉第一个err参数
                        let other_parameters = Array.prototype.slice.call(arguments, 1);
                        resolve.apply(this_obj, other_parameters);
                    }
                });
                func.apply(this_obj, args);
            });
        }
    };
}

当然这里有一个前提要求是回调方法的第一个参数必须是接受错误信息的参数,然后回调函数是这个方法最后一个参数。

例如有一个接口getuser,原来是这样的:

api.getuser = function(id,callback){
    callback(users[id]);
};

回调模式调用会是这样:

api.getuser(123,function(err,user){
    //得到user
});

现在我们给他改造一下,让它同时支持async/await调用,很简单,只是把function用promisify包装一下 :

api.getuser = promisify(function(id,callback){
    callback(users[id]);
});

现在它可以被回调模式调用,也同时支持async/await调用:

var user = await api.getuser(123);

来自:悠游悠游,2017-06-01,原文地址:https://yoyo.play175.com/p/node-promisify.html