function thunkify(fn){ assert('function' == typeof fn, 'function required'); return function(){ var args = new Array(arguments.length); var ctx = this; for(var i = 0; i < args.length; ++i) { args[i] = arguments[i]; } return function(done){ var called; args.push(function(){ if (called) return; called = true; done.apply(null, arguments); }); try { fn.apply(ctx, args); } catch (err) { done(err); } } } };
上面为thunkify模块的源码。
以前当我们调用的时候带有callback的方法的时候都是这样的
function demo(parameter1,parameter2,callback){ try{ //do somethings var result=1; callback(null,result); } catch(err){ callback(err); } }
当使用thunkify之后
var process1=thunkify(demo);//返回一个无参数function var process2=process1(1,2); //返回一个接受一个done参数的function process2(function(err,data){});//真正的执行demo函数
我个人就一直在process2的方法上一个转不过去,知道这样执行了,但是就是思维跟不上。
特此详细记录分析下。
当调用process2的时候,我们能看到通过闭包,让args保存了process1中传入的参数。在process2中,将此时传入的参数push到args中,这样就能凑齐代码块2中的所有参数,只不过此时代码块2中的callback被一个无参数function代替。这样执行demo函数的时候,err和得到的data都传入到该无参函数中,然后利用该函数的arguments内置变量和apply来使用argumeng数组能够一一对应demo中的callback中的参数(arguments是一个数组,apply可以改变函数中的this指向,并通过一个数组来传递参数)。这正通过该无参数的function来调用了真正的callback。如果出现了error,内部没有捕获的话,则在外边直接调用callback捕获。
该模块可以和co模块使用,当yield一个function的时候,thunkify模块就非常有用,co和thunkify的一起使用将在另一个随笔中分析。