【问题标题】:Why not just call a function from another function instead of using a callback?为什么不直接从另一个函数调用一个函数而不是使用回调呢?
【发布时间】:2016-09-25 04:31:06
【问题描述】:

我有点困惑,不是关于回调的用途,而是因为我看到回调经常用于似乎不需要将函数作为参数传递给另一个函数的场景,因为您可以调用该函数您希望在当前函数中的代码执行完毕后调用。例如:

function hello( a , b ) {
    var result = a + b; 
    myFunction();
}

myFunction() {
    //code
}

hello(1,2);

令人困惑的是,我见过很多在场景中使用回调的示例,就像我编写的第一个代码一样简单,在我看来根本不需要回调:

function hello(a, b, callback) {
    var result = a + b;
    callback();
}

myFunction() {
    //code
}

hello(1, 2, myFunction);

我在那里使用了回调,但我可以在代码执行后调用函数myFunction,而不将myFunction 作为参数传递。我知道框架或库不知道代码执行完成后要调用的函数的名称,因此将稍后要调用的函数作为参数传递似乎是有意义的,但是当您知道函数的名称时你想在函数中执行任何代码之后调用它,为什么不像我在我给出的第一个示例中那样调用它呢?我会很感激你的帮助。谢谢

【问题讨论】:

  • 如果它与您发布的代码完全一样(添加a+b)那么当然没有理由。但有时函数会异步执行某些操作(例如进行 ajax 调用),并且您希望函数等到 ajax 调用完成。 (比如当你希望回调作用于你收到的数据时)
  • 您能举一个您认为没有必要的回调示例吗?回调通常用于异步函数。
  • 现在讲的是同步性,但是知识:调用者通常不知道该调用什么;或范围 - 调用者在不同的范围中定义。
  • 有趣的地方通常不是函数被调用的地方,而是a) 它被调用(通常不是紧跟在函数返回) 和 b) 调用它的参数是什么
  • 也许this 会帮助你..

标签: javascript


【解决方案1】:

好处 1

回调很好的原因之一是您可以使用任何回调调用您的函数:

hello(1, 2, myFunction1);
hello(1, 2, myFunction2);
...
hello(1, 2, anyFunctionAtAll);

如果不可能将回调作为参数传递,您的hello 将始终执行 myFunction,因为它已固定在您的函数代码中。

好处2

另一个原因是,使用回调可以防止阻塞长时间运行的操作。您在函数操作完成后传递一个回调以运行,当它正在处理时,它将控制权交还给主事件循环而不是阻塞。

例如,如果您要执行这些操作:

hello(1, 2, myCallback);
console.log('Im not waiting for hello!')

如果您的 myCallback 函数处理时间过长,控制台操作不会等待它终止执行。


如果你想了解更多,知道任何其他 javascript 警告,我推荐 thisthis


结论

如果您认为您不会从其中一件事情中受益,那么在您的场景中不需要回调。

【讨论】:

  • 他已经明白了:“我知道一个框架或库不知道你想要调用的函数的名称 [...] 所以传递你想要稍后调用的函数作为论点似乎有道理”。他问你为什么不直接写hello(1, 2); myFunction1(); hello(1, 2); myFunction2();
  • 这不是回调的用例。它也可以很容易地成为hello(1, 2); myFunction1();
  • @Bergi 这不是 OP 所要求的(请参阅第一个示例和问题的最后一句话)“为什么不像我在我给出的第一个示例中那样调用它”。在第一个示例中,他们在调用者函数中显式调用了一个函数,而不是在它完成之后。因此:对 OP 提出的问题的一个完全有效的答案。
  • @zerkms:我不确定——但是是的,这是一个措辞不当的问题。
  • @4castle "这不是回调的用例" --- 它几乎是。
【解决方案2】:

您可以使用它的一个原因是您可以将 myFunction 作为匿名函数调用

function hello( a , b, callback ) {
    var result = a + b; 
    callback();
}

hello(1,2, function() {
   // your stuff here
});

第二个原因是如果你使用第三方 API 会怎样,例如你向端点发出 API 请求并等待响应?

$.get('api/some/url', function() {
   // This is your callback that get function provides you
})

或者您可能正在使用某些库,例如 jquery

$("p").hide("slow", function(){
   // Callback that will be executed after.
});

【讨论】:

    【解决方案3】:

    您在上面给出的示例对于回调来说不是一个很好的用例,imo。您通常不想简单地以程序方式执行回调函数,您希望该回调函数指示其传递给的包含函数的行为。这样,包含函数可以根据其给定的上下文/状态表现出不同的行为。

    这是一个例子:

    function modifyArray(array, callback) {
      var modifiedArray = [];
    
      for (var i = 0; i < array.length, i++) {
        modifiedArray.push(callback(array[i]));
      }
    
      return modifiedArray;
    }
    

    注意回调函数是如何不简单地执行的?它实际上规定了包含函数修改参数数组元素的方式。

    这样,您可以编写可以在整个代码库中重复使用的高度灵活的函数。

    【讨论】:

    • 但我不能这样做:function modifyArray(array) { var modifiedArray = []; for (var i = 0; i
    • 如果数组是回调的参数,为什么不能作为 myFunction 的参数呢?仅仅是因为可重用性,在这种情况下,回调会有益吗?
    • @codebmanj 这是关于模块化的。想想像.map().filter() 这样的函数。如果将数组传递给函数,它必须自己完成所有迭代,而不是由map() 完成。
    • @Barmar 所以你的意思是为什么将数组传递给一个函数必须自己完成所有的迭代,而不是使用一个已经完成的函数,比如“map”?
    • @codebmanj 没错。像.forEach() 这样的函数的全部意义在于您不必自己编写for(var i = 0; i &lt; array.length, i++) 循环。
    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 2016-08-26
    • 2020-08-26
    相关资源
    最近更新 更多