Javascript 使用闭包委派正在运行的回调

Javascript 使用闭包委派正在运行的回调,javascript,node.js,Javascript,Node.js,我正在处理一个模块,其中有一个接受回调的函数,在它内部调用另一个也接受回调的函数,与此类似 函数doSomething(参数…,回调){ //做些工作 SomeOther函数(参数..,回调2) //...??? } 我的方法是doSomething()是一个模块的入口点,该模块封装了特定于某个任务的某些逻辑,并通过doSomething()的回调参数与其他组件通信,在someOtherFunction()中,它还可以调用其他进行回调的函数 是否可以使用闭包将提供给doSomething()的第

我正在处理一个模块,其中有一个接受回调的函数,在它内部调用另一个也接受回调的函数,与此类似

函数doSomething(参数…,回调){
//做些工作
SomeOther函数(参数..,回调2)
//...???
}

我的方法是doSomething()是一个模块的入口点,该模块封装了特定于某个任务的某些逻辑,并通过doSomething()的回调参数与其他组件通信,在someOtherFunction()中,它还可以调用其他进行回调的函数

是否可以使用闭包将提供给doSomething()的第一个回调和提供给someOtherFunction()的第二个回调包装起来(如果是这样的话,这是否是一种好的做法)

`function wrapCallbacks(err_cb2, arg_to_callback_2){
          function callback(err, res){
                   //first callback logic
          }
          function callback2(err, res){
                   //second callback logic
                   callback(err, res)
          }
          callback2(err_cb2, arg_to_callback_2)
}`
并将此函数作为对someOtherFunction()的回调提供,如果需要,它可以在内部对其他回调执行相同的操作,这样回调将以“后进先出”的顺序执行,这样我就可以在整个模块完成其工作后执行第一个回调

PS:我是一名javascript程序员新手,如果有人能指出我对javascript的理解中任何明显的误解,我将不胜感激

我正在进行最后一年的项目,我试图构建一个点对点系统,允许开发者以接近常规客户端服务器SPA和基于REST的应用程序的方式构建分布式点对点应用程序,我试图通过构建一个本地服务器来实现这一点,该服务器将侦听来自本地计算机上浏览器的请求(本质上是基于客户端服务器的请求,类似于RESTful API),并将它们转换为消息,检索和存储数据,并将其作为浏览器启动的第一个API调用的结果提供

我正在使用分层体系结构来分离责任并提供抽象层,所讨论的函数sendMessage_interface()是堆栈最后一层的入口点,该层负责将对等ID解析为套接字以用于通信,因此该函数将从用户处获取类似“ID”的参数,执行一些数据库操作以检索关联的IP—通过调用resolveID()函数—resolveID()函数将接受回调并将其结果—对等套接字—作为参数提供,但是sendMessage_接口()上层还提供了一个回调函数,在从另一个对等方收到响应后执行,这就是为什么我需要“后进先出”执行它

`this.comms_gateway_sendMessage_interface = function({destID, data, 
resolveID, checkMessageObject, callback}){

    if(!(destID && data && resolveID && callback) ||
    !(typeof(destID) === 'number') ||
    !(typeof(resolveID) === 'function') ||
    !(typeof(callback) === 'function'))
    {
        throw new TypeError('Invalid or missing Argument');
    };
    if(checkMessageObject && typeof(checkMessageObject) === 'function'){
        checkMessageObject(data);
    };

    resolveID({ID : destID, data : data, callback : wrapCallback });
};`

回调是JavaScript的一个主要特性。函数是数据这一事实使得函数很容易用作其他函数的参数。在贸易中,这通常指的是高阶函数

闭包是另一个主要功能:

  • 内部函数继承外部函数的作用域,这使得管理变量作用域更加容易
  • 如果外部函数已完成,但内部函数尚未运行,则会保留外部作用域变量,以便在内部函数运行时使用它们的数据
只有在外部函数内部定义了内部函数时,闭包功能才可用。在另一个函数中引用函数不足以使闭包变量可用。我们说JavaScript有词法范围:范围是在定义代码的地方严格定义的

处理多个回调总是很尴尬。如果不需要持久化闭包变量,可以执行以下操作:

window.setTimeout(fn1,1000);

function fn1() {
    alert('one');
    window.setTimeout(fn2,1000);
}
function fn2() {
    alert('two');
    window.setTimeout(fn3,1000);
}
function fn3() {
    alert('three');
}
不涉及嵌套,并且完全可维护

但是,如果您希望在下一个函数中使用来自一个函数的数据,则下一个函数需要位于第一个函数中才能访问其变量:

window.setTimeout(fn1,1000);

function fn1() {
    var data=0;
    alert(`data ${++data}`);
    window.setTimeout(fn2,1000);
    function fn2() {
        alert(`data ${++data}`);
        window.setTimeout(fn3,1000);
    }
    function fn3() {
        alert(`data ${data++}`);
    }
}
如果第三个函数需要使用第二个函数生成的数据,情况会变得更糟:

window.setTimeout(fn1,1000);

function fn1() {
    var data=0;
    alert(`data ${++data}`);
    window.setTimeout(fn2,1000);
    function fn2() {
        var stuff=3;
        alert(`data ${++data + stuff}`);
        window.setTimeout(fn3,1000);
        function fn3() {
            alert(`data ${++data + stuff}`);
        }
    }
}
这被亲切地称为回调地狱,您可以理解,如果可能,为什么要避免它。但是,如果函数是在另一个函数中定义的,那么这是回调从闭包变量中获益的唯一方法

因此,简短的回答是,是的,这是可能的,是的,这是一种良好的做法,因为这是做这类事情的唯一传统方式


更现代的JavaScript有一种替代方法称为promises:它们允许您链接回调函数,而不是嵌套回调函数,因此您可以使用更线性的方式编写代码。

这将导致回调地狱,您能否提供一些您实际想要实现的内容的背景信息,以及为什么您需要LIFO来执行回调。@TGW通过编辑添加了更多信息。这消除了我的许多误解,谢谢。我现在正处于学习承诺的过程中,所以如果你能帮助我,在你使用的例子中,使用承诺方法看起来是这样的:fn1()将有执行这个代码<代码> fn2()的代码。然后(函数fn3()){//Log}。是吗?@hmoho简短的回答是肯定的,但给我一天左右的时间来重做这个例子。我还应该提到,使用闭包变量的替代方法是将它们作为参数传递。这在传统的回调方法中很棘手,但是您可以使用
bind
方法生成一个包含新参数的新函数。使用承诺使这一部分更简单。@Manngo将变量和数据从一个函数传递到另一个函数非常容易,无需回调地狱-例如,使用
setTimeout(()=>myFn(data1,data2),1000)
,一点也不棘手。@CertainPerformance是的,我知道,虽然您的示例代码在旧版本的IE中不起作用,但我使用了
setTimeout
作为一个简单的示例