Mer*_*erc 5 asynchronous node.js
我想写一个带有函数的通用包装器,并返回该函数的"异步样式"版本,如果它不是异步开始的话.
麻烦的是,没有简单的方法来知道呼叫是同步还是异步.所以...这基本上"无法完成".对?
(请注意,包装器应将同步函数协调为异步样式,并单独使用LEAVE异步函数)
var wrapper = function( fn ){
return function(){
var args = Array.prototype.splice.call(arguments, 0);
var cb = args[ args.length - 1 ];
// ?!?!?!?!?
// I cannot actually tell if `fn` is sync
// or async, and cannot determine it!
console.log( fn.toString() );
}
}
var f1Async = wrapper( function( arg, next ){
next( null, 'async' + arg );
})
var f2Sync = wrapper( function( arg ){
return 'sync' + arg;
})
f1Async( "some", function(err, ret ){
console.log( ret );
});
f2Sync( "some other", function(err, ret ){
console.log( ret );
});
Run Code Online (Sandbox Code Playgroud)
在 javascript 中,无法检查函数的最后一个参数是否是函数,因为在 javascript 中,您没有定义参数的类型。
我的解决方案的工作原理是获取函数中的参数列表,然后使用 RegExp 来查看该参数是否用作函数。此外,在不直接使用回调的情况下(例如将其传递给其他东西),它有一个被视为回调的参数名称列表。
代码是:
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var CALLBACK_NAMES = [ "next", "done", "callback", "cb"];
function getParamNames(func) {
var fnStr = func.toString().replace(STRIP_COMMENTS, '')
var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(/([^\s,]+)/g)
if(result === null)
result = []
return result
}
function checkIfParamIsFunction(func, paramName){
var fnStr = func.toString();
if (fnStr.replace(new RegExp("(" + paramName + "\s*\([A-Za-z0-9,\.]*\)?!{|" + paramName + ".apply\([A-Za-z0-9,\.]*\)|" + paramName + ".call\([A-Za-z0-9,\.]*\))", ""), "{<._|/}") != fnStr) { // Remove All Calls to the arg as a function, then check to see if anything was changed.
return true;
} else {
return false;
}
}
function makeAsync(func) {
var paramNames = getParamNames(func);
if (checkIfParamIsFunction(func, paramNames[paramNames.length - 1])
|| CALLBACK_NAMES.indexOf(paramNames[paramNames.length - 1]) != -1) {
// Function Is Already async
return func;
} else {
return function () {
var args = Array.prototype.slice.call(arguments);
var cb = args.pop();
cb(func.apply(this, args));
}
}
}
function test1(a){
return (a+' test1');
};
function test2(a, callback){
return callback(a+' test2')
};
function main(){
var tested1 = makeAsync(test1);
var tested2 = makeAsync(test2);
tested1('hello', function(output){
console.log('holy shit it\'s now async!!');
console.log(output);
});
tested2('world', function(output){
console.log('this one was already async tho');
console.log(output);
});
}
main();
Run Code Online (Sandbox Code Playgroud)
只需调用makeAsync(function)它就会返回一个异步函数。function.apply如果您使用或 ,这将起作用.call。