如何实现可重用的回调函数
How to implement reusable callback functions
我对JavaScript相当陌生,我正在节点工作,这需要对异步编程和回调设计有很好的理解。 我发现使用嵌入式函数非常容易,即使你的回调是多级的深度。 您的嵌入式回调最终只是闭包。
但是,当您有几层回调时,其中许多回调在执行路由中是相似的,您最终会在单独的回调链中一遍又一遍地重写大量回调代码。 例如,如果下面的 mycb1 和 mycb2 定义被移到 A 之外,它们就不再隐式访问 A 的变量,因此不再充当闭包。
具有嵌入式定义的示例,其中它们充当闭包。
mod.A=function(){
var mycb1=function(err){
if (!err){
var mycb2=function(err){
cb(err);
};
mod.foo2(args,mycb2);
}
else{cb(err);}
};
mod.foo1(args,mycb1);
}
mod.foo1 = function(args,cb){
//do some work
cb(err);
};
mod.foo2 = function(args,cb){
//do some work
cb(err);
}
//execute
mod.A();
我想执行以下操作,但能够更改 mycb1 和 mycb2 函数的变量范围,以便它们可以用作调用它们的闭包。例如:
var mycb2=function(err){
...
cb(err);
};
var mycb1=function(err){
if (!err){
mod.foo2(args,mycb2); //but have it act like a closure to mycb1
}
else{cb(err);}
};
mod.A=function(){
...
mod.foo1(args,mycb1); //but have it act like a closure to A
}
mod.foo1 = function(args,cb){
//do some work
cb(err);
}
mod.foo2 = function(args,cb){
//do some work
cb(err);
}
我知道我可以实现一种设计,该设计可以在 mod 级别设置变量,以便 mod 级别函数可以访问它们。 然而,这似乎在某种程度上污染了 mod 范围,变量可能只能由它的少数方法使用。 我也知道我可以传入变量,以便在执行它们时可供回调访问。 但是,如果我了解JS和回调的工作原理,我必须将它们传递给fooX,然后让foo将它们传递给回调。 这似乎也不是一个好的计划。是否可以更改函数的变量范围,使其像从执行点而不是定义点开始的闭包? 如果没有,模块化回调代码以便可以重用的最佳方法是什么?
一般来说,必须创建另一个可以访问闭包的内联函数是无法回避的。您可以通过一个简单的匿名函数将一些参数作为参数传递给父回调,同时接受其余参数(即部分函数),或者使用 Function.bind() 创建部分函数本身来创建内联函数。
例如,如果您最初有:
function(...) {
// closure vars x1, y1
foo.bar( function(result) {
// do something with x1 and y1
});
}
您可以将其提取为:
var callback = function(x1, y1, result) {
// do something with x1 and y1
};
function(...) {
// closure vars x1, y1
// option 1: make your own partial function
foo.bar( function(result) { return callback(x1, y1, result); });
// with ES6: foo.bar( (result) => callback(x1, y1, result); });
// option 2: use Function.bind
foo.bar( callback.bind(this, x1, y1); );
}
这是一个没有闭包和嵌套的嵌套回调示例。它抓取指定的页面,找到第三个链接,然后向用户显示该链接的来源。
在这种情况下,当从控制台中的此处运行并馈送主页时,注销页面是第三个链接,并且会提醒其内容。
所有的回调都是同级,没有外部状态变量,只有纯函数异步:
// look ma, no nesting!
function ajax(a, c) {
var e = new XMLHttpRequest;
e.onload= ajaxOnload.bind(this, c, e);
e.open( "GET", a, !0);
e.send();
return e
}
function ajaxOnload(c, e) {
c(e.responseText, e);
}
function cbFind3(cb, s){
var t=document.createElement("body");
t.innerHTML=s;
var lnk= t.getElementsByTagName("a")[3].href;
ajax(lnk, cb);
}
function grabThirdLinkSource(url, cb){
ajax(url, cbFind3.bind(this, cb));
}
grabThirdLinkSource("/", alert);
这不是最有用的示例,但它确实展示了如何使用 bind() 跨调用链接函数。 我使用了原版 Ajax 并避免了承诺,只是为了展示这种交互方式如何执行而没有任何复杂性。 甚至 Ajax 帮助程序也使用非嵌套函数将 responseText 提供给"核心"回调,而不是事件或整个 xhr 对象。
- JavaScript回调函数
- 如何在回调函数中执行流
- 回调函数中传递参数的困难(Google Map API Markers)
- 如何正确地将参数传递给RequireJS回调函数
- 回调函数在python代码中离线
- 从AJAX回调函数中分离数据
- 赋值后的回调函数
- 如何在javascript回调函数中返回多个变量
- 函数表达式,返回回调函数
- 等待回调函数执行
- JavaScript回调函数和Google Feed API
- 如何从ajax成功回调函数中读取javascript变量
- 正在保存JavaScript内部回调函数中的值
- 有没有什么方法可以停止Jquery中的animate(也可以停止完整的回调函数)
- 如何在javascript中添加带有回调函数的按钮点击事件作为window.conf
- 在Golang回调函数中启用CORS
- 在初始函数完成之前调用回调函数
- jQuery Mobile:如何在$.Mobile.changePage之前运行回调函数
- 即使使用回调函数也无法返回值
- 为什么prototypjs观察到回调函数有绑定