简体   繁体   English

回调、高阶函数、回调队列有什么区别

[英]What is the difference between callback, high-order functions, and callback queue

At this point, I have a question on what exactly is a callback , what makes it different from a high-order function and how does it relate to the concept of callback queue ?在这一点上,我有一个问题,什么是回调,什么使它与高阶函数不同,它与回调队列的概念有什么关系?

From MDN: Callback function来自 MDN: 回调函数

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.回调函数是作为参数传递给另一个函数的函数,然后在外部函数内部调用该函数以完成某种例程或动作。

Looks like there's an overlap with the definition of High-Order Functions.看起来与高阶函数的定义有重叠。 A function that gets passed (and later invoked) to another function.一个被传递(然后被调用)到另一个函数的函数。

This is the MDN example of a callback:这是回调的 MDN 示例:

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('Please enter your name.');
  callback(name);
}

processUserInput(greeting);

No doubt so far.毫无疑问,到目前为止。

I then faced with the idea of Event Loop and Callback queue .然后我遇到了Event LoopCallback queue的想法。

 console.log("me first");

  setTimeout(function asyncLog() {
       console.log("i am the last")
  }, 2000);

  console.log("me second")

Turns out the seTimeout function, is actually a JavaScript wrapper that interfaces under the hood with Web Browser API (timer).原来seTimeout函数实际上是一个 JavaScript 包装器,它在引擎盖下与 Web 浏览器 API(计时器)交互。 setTimeout passes to the Timer API a function (asyncLog) and the timer (2000ms). setTimeout 将函数 (asyncLog) 和计时器 (2000ms) 传递给计时器 API。

When the timer feature (in the web browser) has completed its work, will send the function asyncLog in the callback queue ready to be invoked in the call stack as soon as the JS call stack is (1) Empty and (2) has processed everything in the global execution context.当计时器功能(在 Web 浏览器中)完成其工作时,一旦 JS 调用堆栈为 (1) 空且 (2) 已处理,就会在callback queue准备在调用堆栈中调用的函数asyncLog全局执行上下文中的所有内容。

So after the last line console.log("me second") is processed the Event Loop passes the callback function asyncLog from the callback queue to the call stack, and executes it.所以在处理完最后一行console.log("me second") ,事件循环将回调函数asyncLog从回调队列传递到调用堆栈,并执行它。

The final order is:最后的顺序是:

me first
me second
i am the last

In the first example, even though we are referring to greeting as the "callback" function, my understanding suggests that the entire mechanism of Callback queue gets skipped entirely: we're not doing anything asynchronous and we're not interfacing with the web browser API (everything is self-contained into JS).在第一个示例中,尽管我们将greeting称为“回调”函数,但我的理解表明回调队列的整个机制被完全跳过:我们没有做任何异步操作,也没有与 Web 浏览器交互API(所有内容都包含在 JS 中)。

If so, why do we refer to functions that get passed into other functions as callbacks (and not as simple High-order functions), when they have nothing to do with the callback queue and with the asynchronous world?如果是这样,当它们与回调队列和异步世界无关时,为什么我们将传递给其他函数的函数称为回调(而不是简单的高阶函数)?

A higher-order function is a function that takes another function(s) as an argument(s) and/or returns a function to its callers.高阶函数是将另一个函数作为参数和/或将函数返回给其调用者的函数。

A callback function is a function that is passed to another function with the expectation that the other function will call it. 回调函数是传递给另一个函数并期望另一个函数调用它的函数。

So a callback is not necessarily itself a higher-order function, but a function which receives a callback as an argument is .因此,回调本身不一定是高阶函数,而是接收回调作为参数的函数 Consider a very common case, the DOM event listener:考虑一个非常常见的情况,DOM 事件侦听器:

elem.addEventListener('click', console.log);

Here, .addEventListener is a higher-order function that takes another function ( console.log ) which it then calls.这里, .addEventListener是一个高阶函数,它接受另一个函数( console.log ),然后调用它。 Although console.log is a callback here, it is not in this case acting as a higher-order function itself.尽管console.log在这里是一个回调,但在这种情况下它本身并不充当高阶函数。

The event loop is a mechanism exposed to you by the underlying runtime.事件循环是底层运行时向您公开的一种机制。 Here we are going to imagine that we have to do this manually, using an array as a queue:在这里,我们将想象我们必须手动执行此操作,使用数组作为队列:

const queue = [];
const setTimeout = (f, ...args) => {
  queue.push([f, args]);
};

const runQueuedCallbacks = () => {
  let queued;
  while (queued = queue.shift()) {
    let [f, args] = queue;
    f(...args);
  }
};

setTimeout(console.log, 'first');   // queues a call to log
setTimeout(console.log, 'second');  // queues a call to log
console.log('zero-th');             // directly calls log, prints first

// at this point there's no more code to execute, so runQueuedCallbacks runs
// and sequentially steps through the enqueued callbacks.

In real life it's a little more complicated than this because of things like microtask resolution (also what happens when a queued callback queues another callback) but that should hopefully give you a decent picture.在现实生活中,由于诸如微任务解析之类的事情(还有排队的回调排队另一个回调时会发生什么),它比这更复杂一点,但这应该会给你一个不错的画面。

A higher-order function is a function that takes another function(s) as an argument(s) and/or returns a function to its callers.高阶函数是将另一个函数作为参数和/或将函数返回给其调用者的函数。 Here, the function(s) which is passed as the argument is called as the call-back function.这里,作为参数传递的函数被称为回调函数。 However, the callback function may be a higher order function too, or it may be not.但是,回调函数也可能是高阶函数,也可能不是。 Lets see examples.让我们看看例子。

function printString(callbackHof, callback_only, str) {
   str +=' concated first';
  callbackHof( callback_only,str);
}

function concatFirst(callback_only, str)
{
  callback_only(str);
}

function concatAgain(str)
{
  str += ' contated again';
  console.log(str);
}

printString(concatFirst, concatAgain, 'anything');

The output is ='anything concated first contated again' for clarification.为了澄清,输出是 ='首先连接的任何内容'。

Here printString() is a higher order function which takes two functions and a string as arguments.这里的 printString() 是一个高阶函数,它接受两个函数和一个字符串作为参数。 The function arguments of printString() are concatFirst() and concatAgain(), these concatFirst() and concatAgain() fumctions are callback functions by definition. printString() 的函数参数是 concatFirst() 和 concatAgain(),根据定义,这些 concatFirst() 和 concatAgain() 函数是回调函数。

Here, concatFirst() is both callback and higher order function as it is passed as printString()'s argument, then also takes concatAgain() callback function as it's own input.在这里, concatFirst() 既是回调函数又是高阶函数,因为它作为 printString() 的参数传递,然后还将 concatAgain() 回调函数作为它自己的输入。

And, concatAgain() is just a callback function, because it is called with just a string argument & no further function argument.而且, concatAgain() 只是一个回调函数,因为它只用一个字符串参数调用而没有进一步的函数参数。

Finally, callback queue is the mechanism that browsers or javascript compilers follow to perform asynchronous & callback operations perfectly with the help of event-loop.最后,回调队列是浏览器或javascript编译器在事件循环的帮助下完美执行异步和回调操作所遵循的机制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM