为什么在 JavaScript 中使用回调,它的优点是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7070495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:43:13  来源:igfitidea点击:

Why use callback in JavaScript, what are its advantages?

javascriptjquery

提问by Harke

Could someone explain, why do we use callback in JavaScript? I found examples, but they could be implemented by using the normal functions. What is the advantage of using it? I got answers to "how" to use it and not "why and when" do we need to use it.

有人可以解释一下,为什么我们在 JavaScript 中使用回调?我找到了例子,但它们可以通过使用普通函数来实现。使用它有什么好处?我得到了“如何”使用它的答案,而不是“为什么以及何时”我们需要使用它。

Typically, I found it being used in AJAX. on the httpRequest.onreadystatechange. Is this similar to Java's multi-threading? How and where is the listener for the response? Is asyncronous programming akin to multi-threading?

通常,我发现它在 AJAX 中使用。上httpRequest.onreadystatechange。这类似于Java的多线程吗?响应的侦听器如何以及在哪里?异步编程类似于多线程吗?

In the following code, how is the flow of control:

在下面的代码中,控制流程是怎样的:

function some_function(arg1, arg2, callback) {
  var my_number = Math.ceil(Math.random() * (arg1 - arg2) + arg2);
  callback(my_number);
  some_different_function_not_callback(arg1);
}
some_function(5, 15, function(num) {
   console.log("callback called! " + num);
});

From the JQuery website:

从 JQuery 网站:

The special thing about a callback is that functions that appear after the "parent" can execute before the callback executes" (ref: http://docs.jquery.com/Tutorials:How_jQuery_Works)

回调的特殊之处在于出现在“父”之后的函数可以在回调执行之前执行”(参考:http: //docs.jquery.com/Tutorials: How_jQuery_Works

Could someone explain me this line with an example?

有人可以用一个例子向我解释这一行吗?

采纳答案by EMI

The main browser process is a single threaded event loop. If you execute a long-running operation within a single-threaded event loop, the process "blocks". This is bad because the process stops processing other events while waiting for your operation to complete. 'alert' is one of the few blocking browser methods: if you call alert('test'), you can no longer click links, perform ajax queries, or interact with the browser UI.

主浏览器进程是一个单线程事件循环。如果您在单线程事件循环中执行长时间运行的操作,该进程将“阻塞”。这很糟糕,因为该进程在等待您的操作完成时停止处理其他事件。'alert' 是少数阻止浏览器的方法之一:如果您调用 alert('test'),您将无法再单击链接、执行 ajax 查询或与浏览器 UI 交互。

In order to prevent blocking on long-running operations, the XMLHttpRequest provides an asynchronous interface. You pass it a callback to run after the operation is complete, and while it is processing it cedes control back to the main event loop instead of blocking.

为了防止长时间运行的操作阻塞,XMLHttpRequest 提供了一个异步接口。在操作完成后,您向它传递一个回调以运行,并在它处理时将控制权交还给主事件循环而不是阻塞。

There's no reason to use a callback unless you want to bind something to an event handler, or your operation is potentially blocking and therefore requires an asynchronous programming interface.

没有理由使用回调,除非您想将某些内容绑定到事件处理程序,或者您的操作可能会阻塞并因此需要异步编程接口。

This is an excellent video discussing more about the event loop used in the browser, as well as on the server side in node.js.

这是一个很好的视频,更多地讨论了浏览器中使用的事件循环,以及 node.js 中的服务器端。

EDIT: that convoluted line from the jQuery documentation just means that the callback executes asynchronously as control is ceded back to the main event loop.

编辑:来自 jQuery 文档的那条令人费解的行只是意味着当控制权交还给主事件循环时,回调异步执行。

parent_function(function () { console.log('Callback'); });
parent_doesnt_block(); // <-- function appears after "parent"
therefore_execution_continues();
// Maybe we get 'Callback' in the console here? or maybe later...
execution_still_continues();

回答by Alex Wayne

Not quite like multithreading...

不太像多线程...

You use a callback anytime you need to wait on something external to your primary JS code. In a browser this is used a ton for AJAX, and in node.js it's used for every single thing that calls out to the system (file access, networks access, database requests, etc).

您可以在需要等待主 JS 代码外部的内容时随时使用回调。在浏览器中,它大量用于 AJAX,而在 node.js 中,它用于调用系统的每一件事(文件访问、网络访问、数据库请求等)。

Let's say you want to fire an ajax request everytime a user clicks a button. Now lets say that ajax request takes 10 seconds to complete. The user then clicks 10 of these buttons before those 10 seconds are up. This would repeatedly call a function like this:

假设您想在每次用户单击按钮时触发 ajax 请求。现在假设 ajax 请求需要 10 秒才能完成。然后,用户在 10 秒结束之前单击其中的 10 个按钮。这将重复调用这样的函数:

var clicked = function() {
  doAjax('/some/path.json', function(result) {
    updatePageWith(result.widgets);
  });
};

This runs code in the JS engine for only long enough to make the request. Then it idles while it waits. Other JS can run at this point, the UI is totally fluid and interactive, everything is awesome. Then suddenly, all 10 of those requests resolve at once. And then our callback is invoked 10 times like magic.

这在 JS 引擎中运行代码的时间只够发出请求。然后它在等待时空闲。其他 JS 可以在这一点上运行,UI 完全流畅和交互,一切都很棒。然后突然间,所有 10 个请求同时解决。然后我们的回调像魔术一样被调用 10 次。

This works because every time we call clicked()we are creating a new function object, and passing it to the doAjax()function. So there are 10 unique callback function objects hanging out in memory, each one bound to a specific request by the doAjax()function. When a request returns, it finds the associated callback object and calls it.

这是有效的,因为每次我们调用clicked()我们都会创建一个新的函数对象,并将其传递给doAjax()函数。所以有 10 个独特的回调函数对象挂在内存中,每个对象都绑定到doAjax()函数的特定请求。当请求返回时,它会找到关联的回调对象并调用它。

The huge advantage here is that, although javascript is single threaded, you never tie up that thread with waiting. If you JS thread is busy, it should only ever be because it's actively running code. So even though JS is single threaded, it's trivial for your code to implicitly hold the state of any number of any kind of asynchronous tasks.

这里的巨大优势在于,尽管 javascript 是单线程的,但您永远不会用waiting 来占用该线程。如果您的 JS 线程很忙,那应该只是因为它正在积极运行代码。因此,即使 JS 是单线程的,您的代码也可以隐式保存任意数量的任意类型的异步任务的状态。

The synchronousmethod of callbacks are used for a different purpose usually. Like listeners or delegates. Like telling object A to callback when it's data changes. While not strictly asynchronous, you usually aren't calling that callback immediately. Instead it will be called later in response to some sort of user action of event.

回调的同步方法通常用于不同的目的。像听众或代表。就像告诉对象 A 在数据更改时回调一样。虽然不是严格异步的,但您通常不会立即调用该回调。相反,它将在稍后调用以响应某种用户事件操作。

回答by GBa

Because the javascript being executed is Asynchronous, therefore if you just put any old function after making the asynchronous request, it will likely be called before the original request completes. The original request will return as soon as it BEGINS (is sent out), not completes.

因为正在执行的javascript是异步的,所以如果你只是在发出异步请求后放置任何旧函数,它很可能会在原始请求完成之前被调用。原始请求将在开始(发出)后立即返回,而不是完成。

If you need to do something with the result of the asynchronous request, or chain together requests, etc you will need a callback to ensure the next step doesn't begin before the previous step is finished.

如果您需要对异步请求的结果做一些事情,或者将请求链接在一起等,您将需要一个回调来确保在上一步完成之前下一步不会开始。

回答by outis

Callbacks are used all over the place in JS, particularly in jQuery.

回调在 JS 中无处不在,尤其是在 jQuery 中。

One place you need to use a callback is anywhere the language doesn't give you coordination. Coordination means code doesn't execute until the data it needs is ready. Synchronous calls are coordinated; the call doesn't return until the sub-computation is finished. Asynchronous calls don't give you coordination, so you need a callback.

您需要使用回调的地方是语言无法提供协调的任何地方。协调意味着代码在它需要的数据准备好之前不会执行。同步调用协调;在子计算完成之前,调用不会返回。异步调用不会给你协调,所以你需要一个回调。

  • Event-driven computation can be uncoordinated, so event handlers are callbacks:

    <input id="a" /> <button id='add'>+</button> <input id="b" /> = <span id="c"></span>
    <script type="text/javascript">
      $('#add').click(
          function() {
              $('#c').text(parseInt($('#a').val()) + parseInt($('#b').val()));
          }
      );
    </script>
    

    In JS specifically, coordination for event dispatch (e.g. the DOM dispatchEvent, jQuery triggerand IE fireEventmethods) is left unspecified (except for nested DOM events, which are synchronous). If you trigger an event, the handlers may be deferred and execution immediately return to whatever is after the trigger. Event handlers are usually called synchronously, but they don't need to be.

  • JQuery effectsusually take a callback to execute once they finish. Animation functions are asynchronous so that they don't block the rest of the script.

  • 事件驱动的计算可能是不协调的,因此事件处理程序是回调:

    <input id="a" /> <button id='add'>+</button> <input id="b" /> = <span id="c"></span>
    <script type="text/javascript">
      $('#add').click(
          function() {
              $('#c').text(parseInt($('#a').val()) + parseInt($('#b').val()));
          }
      );
    </script>
    

    特别是在 JS 中,事件调度的协调(例如 DOM dispatchEvent、jQuerytrigger和 IEfireEvent方法)是未指定的(嵌套 DOM 事件除外,它们是同步的)。如果您触发一个事件,处理程序可能会被推迟,并且执行会立即返回到触发之后的状态。事件处理程序通常是同步调用的,但并非必须如此。

  • JQuery效果通常在完成后执行回调。动画函数是异步的,因此它们不会阻塞脚本的其余部分。

Callbacks are also useful for functions that define the outer part of some computation, but leave an inner part undefined. Here are some examples:

回调对于定义某些计算的外部部分但未定义内部部分的函数也很有用。这里有些例子:

  • You can use callbacks to filter collections:

    // get odd items
    $([0,1,2,3,4,5,6,7,8,9]).filter(function (i) {return this % 2;})
    // or:
    $.grep([0,1,2,3,4,5,6,7,8,9], function (x, i) {return x % 2;});
    
  • Array.sorttakes a callback so you can define how elements are compared.

    [{name: 'foo', id: 1}, {name: 'bar', id: 5}, {name: 'baz', id: 3}]
        .sort(function (a,b) { 
            return a.name.localeCompare(b.name); 
        })
    
  • 您可以使用回调来过滤集合:

    // get odd items
    $([0,1,2,3,4,5,6,7,8,9]).filter(function (i) {return this % 2;})
    // or:
    $.grep([0,1,2,3,4,5,6,7,8,9], function (x, i) {return x % 2;});
    
  • Array.sort接受回调,以便您可以定义元素的比较方式。

    [{name: 'foo', id: 1}, {name: 'bar', id: 5}, {name: 'baz', id: 3}]
        .sort(function (a,b) { 
            return a.name.localeCompare(b.name); 
        })
    

Some of jQuery's DOM manipulation methods (such as append, prependand wraptake a callback to construct an element based on context provided by the jQuery method. You could view the callback as providing an inner portion of a computation or as a matter of coordination: when the outer computation is started, the needed data to build the new DOM elements isn't available; the callback finishes the sub-computations to create the elements when the data becomes available.

一些 jQuery 的 DOM 操作方法(例如append,prependwrap根据 jQuery 方法提供的上下文使用回调构造元素。您可以将回调视为提供计算的内部部分或协调问题:当外部计算开始时,构建新 DOM 元素所需的数据不可用;当数据可用时,回调完成子计算以创建元素。

setTimeoutand setIntervalboth take callbacks to execute after a delay.

setTimeout并且setInterval都在延迟后执行回调。

Starting with version 1.5, jQuery offers deferred objectsas a way of managing multiple callbacks, with various execution dependencies between the callbacks.

从 1.5 版开始,jQuery 提供延迟对象作为管理多个回调的一种方式,回调之间具有各种执行依赖关系。

A callback is very similar to a "continuation", which basically means "the rest of the computation". The difference is that a continuation represents the entirety of the rest of the computation while a callback represents the rest of a sub-computation. Continuations are part of a whole style of programming known as "continuation passing style" (CPS). With continuations, you can create all sorts of interesting control structures. For example, continuations can be used to implement exceptions and coroutines.

回调与“延续”非常相似,基本上意味着“其余的计算”。区别在于,延续代表整个计算的其余部分,而回调代表子计算的其余部分。延续是整个编程风格的一部分,称为“延续传递风格”(CPS)。通过延续,您可以创建各种有趣的控制结构。例如,延续可用于实现异常和协程

Depending on the features of the language engine (in particular, you need tail call optimization), CPS can offer a more efficient approach. Some control structures (such as coroutines) require tail calls, otherwise you'll get a stack overflow*.

根据语言引擎的特性(特别是需要尾调用优化),CPS 可以提供更有效的方法。一些控制结构(例如协程)需要尾调用,否则你会得到堆栈溢出*

回答by Davy8

Callbacks allow single-threaded operations (Javascript is single-threaded) to execute asynchronously.

回调允许单线程操作(Javascript 是单线程的)异步执行。

The most obvious example is AJAX calls, where you have a callback that executes after the AJAX request is done. The AJAX request can take a while, and if it were a normal function call, the whole page would be frozen (can't scroll, can't select text, etc) while the request loads.

最明显的例子是 AJAX 调用,在 AJAX 请求完成后,您有一个回调函数执行。AJAX 请求可能需要一段时间,如果是正常的函数调用,则在请求加载时整个页面将被冻结(无法滚动、无法选择文本等)。

This is achieved through either setTimeoutor setIntervalwhich enqueues a function to be called at a later time while allowing other code to execute in between. So when you're waiting for that AJAX call to finish, other code (which includes the browser updating) is allowed to execute.

这是通过将要调用的函数排入队列的setTimeoutsetInterval来实现的,同时允许其他代码在两者之间执行。因此,当您等待 AJAX 调用完成时,允许执行其他代码(包括浏览器更新)。

Since you want examples other than AJAX, the other common usage for the async nature is for animations. Callbacks are requiredfor animations because it needs to allow the UI to draw.

由于您需要 AJAX 以外的示例,因此异步性质的另一个常见用法是用于动画。回调要求的动画,因为它需要让UI绘制。

Say you wanted to animate a div100px to the right over 5 seconds. Your first instinct might say create a loop and sleep in between. But there is no sleepin Javascript, and even if there was, it would just freeze the UI because nothing can happen while it's sleeping.

假设您想div在 5 秒内向右移动 100 像素的动画。您的第一直觉可能会说创建一个循环并在两者之间睡眠。但是sleep在 Javascript中没有,即使有,它也会冻结 UI,因为它在休眠时不会发生任何事情。

Instead, you need to do something along the lines of increment the position by 10, then call setTimeoutfor 500 ms with a callback to execute the next frame. This would probably be done recursively.

相反,您需要按照将位置增加 10 的方式做一些事情,然后setTimeout通过回调调用500 毫秒以执行下一帧。这可能会递归完成。

An additional use would be just simply to pass functions as parameters, although I'm not sure if the term "callback" is appropriate for that use case. That is the way you've used it in your example, some_functioncan be reused with a variety of functions used as callbacks, so sort of injecting code.

另一个用途只是简单地将函数作为参数传递,尽管我不确定术语“回调”是否适合该用例。这就是您在示例中使用它的方式,some_function可以与用作回调的各种函数重用,因此类似于注入代码。

回答by mohit dutt

Callback itself, as the name suggests (call - back) whenever you need to call a function after the execution of the first one, in those scenarios we need to use a callback. Basically the use of callback helps us when we need to use the result of the first function into another function and of course we can use it in a direct way but what if the first function did not respond to any result and we have already passed it to lower function then it will results to undefined and later if one had tried to mutate that passed value it will result in error like can not mutate or assign value of undefined .

回调本身,顾名思义(call-back),只要你需要在第一个函数执行后调用一个函数,在这些场景中我们就需要使用回调。基本上,当我们需要将第一个函数的结果用于另一个函数时,回调的使用对我们有帮助,当然我们可以直接使用它,但是如果第一个函数没有响应任何结果并且我们已经传递了它怎么办降低函数然后它会导致 undefined ,稍后如果有人试图改变传递的值,它将导致错误,例如 can not mutate 或分配 undefined 的值。

function first(){
  //any call or request that is giving us result say abc
  function second(abc){
    //mutate abc, it can be either array, object or can be another function
  }
}

In these scenarios, we need to use call back as the first function will result in abc but no one knows how much time it will really take.

在这些场景中,我们需要使用回调,因为第一个函数会导致 abc 但没有人知道它真正需要多长时间。

and apart from callback one should use promises or async/ await to make your code more modular and looks more like in synchronous ways

除了回调之外,应该使用 promises 或 async/await 使您的代码更加模块化并且看起来更像是同步方式

回答by Trunk

Why use callback in JavaScript, what are its advantages ?

为什么在 JavaScript 中使用回调,它的优点是什么?

Callback functions are basically functions (either named or anonymous) that are passed into a call on another function as an argument. The JavaScript syntax allows us to treat functions as objects so we can pass a function nameas an argument of another function no problem. But we can also pass the full code of an anonymous functionas an argument too, e.g. in a XMLHttpRequest response handler for a form field validation process:

回调函数基本上是作为参数传递给另一个函数的调用的函数(命名的或匿名的)。JavaScript 语法允许我们将函数视为对象,因此我们可以将函数名称作为另一个函数的参数传递没有问题。但是我们也可以将匿名函数完整代码作为参数传递,例如在表单字段验证过程的 XMLHttpRequest 响应处理程序中:

req.onreadystatechange = function()
    {
        if (req.readyState === 4 && req.status === 200)
        {
            if (req.responseText !== 'Valid')                                                   // Check for invalid field value ...
            {
                document.getElementById(field + 'err').value = req.responseText;                // ... and output detail to error field
                document.getElementById(field + 'err').style.color = 'red';                     // Field comment in red
                document.getElementById(field + '-errchk').innerHTML = '\u00D7';                // Cross mark opposite data field
                document.getElementById(field + '-errchk').style.color = 'red';                 // ... in red
                document.getElementById(field + '-errchk').style.fontWeight = 800;              // ... and bold
            }
            else
            {
                document.getElementById(field + 'err').value = '';                              // Clear error info field
                document.getElementById(field + 'err').style.color = 'green';                   // Field comment in green
                document.getElementById(field + '-errchk').innerHTML = '\u2713';                // Check mark opposite data field
                document.getElementById(field + '-errchk').style.color = 'green';               // ... in green
                document.getElementById(field + '-errchk').style.fontWeight = 800;              // ... and bold
            }
        }
    }

In JavaScript the advantage of using a callback function over using a non-callback function (i.e. a function called within another function which does not include it as a parameter) lies in the callback function's range of accessible data, its scope.

在 JavaScript 中,使用回调函数比使用非回调函数(即在另一个函数中调用的函数不包含它作为参数)的优势在于回调函数的可访问数据范围,即其作用域

Non-callback functions have access to just their own internal scope plus their own global scope plus the parameter values input to them. Beyond this they do not have any unilateral access to the scope of any code block using them. So if we want to have a non-callback function "see" certain vars/consts/functions/collections within the code that calls it, we need to move the declarations of these within the scope of the non-callback function. This is always a bit cumbersome and sometimes very tricky. Otherwise we may need to redefine the non-callback function so that otherwise non-shareable data from the calling code's scope is passed as parameters to it. This of course changes the declaration of the non-callback function and impacts any other code block that uses it.

非回调函数只能访问它们自己的内部作用域加上它们自己的全局作用域以及输入到它们的参数值。除此之外,他们无法单方面访问使用它们的任何代码块的范围。因此,如果我们想让一个非回调函数“看到”调用它的代码中的某些 vars/consts/functions/collections,我们需要将这些声明移动到非回调函数的范围内。这总是有点麻烦,有时非常棘手。否则,我们可能需要重新定义非回调函数,以便将来自调用代码范围的不可共享数据作为参数传递给它。这当然会更改非回调函数的声明并影响使用它的任何其他代码块。

Callback functions have access to both their own scope plus the scope of the code that calls them plus the global scope of the calling code. So callback functions are handier to manage codewise, especially in larger JS applications where data is passed across several module boundaries during execution of a task.

回调函数可以访问它们自己的作用域以及调用它们的代码的作用域以及调用代码的全局作用域。因此回调函数更易于代码管理,尤其是在较大的 JS 应用程序中,其中数据在任务执行期间跨多个模块边界传递。

Callback functions existed in JavaScript from almost the beginning. At the front end of web applications, you'll see them used in things like event listeners, for example if we want to remove the mouse's on-hover text displayed when we hover away from the "Next Month" arrow of a web page calendar :

回调函数几乎从一开始就存在于 JavaScript 中。在 Web 应用程序的前端,您会看到它们用于事件侦听器之类的东西,例如,如果我们想删除鼠标悬停在网页日历的“下个月”箭头之外时显示的悬停文本:

var mouseOut = function(e)      
{
    if (document.getElementById("right-info").innerHTML != "")
    {
        document.getElementById("right-info").innerHTML = "";   
    }
};

nextM.addEventListener('mouseout', mouseOut, false);

At the back end, callbacks were used for asynchronous data transfer between browser and server. They were also used as the original means of ensuring back-end JS scripts that included asynchronous functions (e.g. database queries, network calls, file-system actions, data loading from external devices, etc) would execute in the desired order. Basically, by including a callback function that does the operation needing to be done immediately after the async process as a parameter to the async function, we could ensure its correct sequencing w.r.t. the async process. The scoping privileges of a callback function helped the coding a bit too.

在后端,回调用于浏览器和服务器之间的异步数据传输。它们还被用作确保包含异步功能(例如数据库查询、网络调用、文件系统操作、从外部设备加载数据等)的后端 JS 脚本以所需顺序执行的原始手段。基本上,通过包含一个回调函数来执行需要在异步进程之后立即完成的操作作为异步函数的参数,我们可以确保它在异步进程中正确排序。回调函数的范围权限也对编码有所帮助。

Nowadays use of callback functions at the back end is seldom used as modern JavaScript includes a Promiseobject that encapsulates handling of asynchronous processes in a clearer and more scalable way.

如今在后端很少使用回调函数,因为现代 JavaScript 包含一个Promise对象,该对象以更清晰、更可扩展的方式封装异步进程的处理。

But it's still good to know what they are and where they can be effectively used.

但是知道它们是什么以及它们可以在哪些地方有效使用仍然很好。

回答by Vizz85

Another point is code testability.

另一点是代码可测试性。

Let's say you have this scenario:

假设您有以下场景:

function pushToDatabase(data) {
  // do some API call...
}

function handleData(someData) {
  // some logic

  pushToDatabase(someData);
}

When unit testing maybe you don't want to look into the database if new data is available but just check if pushToDatabasefunction was called with the right data, so it can be refactored to:

在进行单元测试时,如果有新数据可用,您可能不想查看数据库,而只是检查是否pushToDatabase使用正确的数据调用了函数,因此可以将其重构为:

function pushToDatabase(data) {
  // do some API call...
}

function handleData(someData, callback) {
  // some logic

  callback(someData);
}

and called with handleData(someData, pushToDatabase).

并用 调用handleData(someData, pushToDatabase)

This could be a test with Jest:

这可能是对 Jest 的测试:

const aModule = require('./aModule');

describe('aModule', () => {
  it('should push data to a database', () => {
    const mockFn = jest.fn();
    const myData = 'Hello!';

    aModule.handleData(myData, mockFn)

    expect(mockFn).toHaveBeenCalledWith(myData);
  });
});

Linkto working Repl.

链接到工作 Repl。

回答by madhu_karnati

A callback function is executed after the current effect is finished. A more detailed example available here.

当前效果完成后执行回调函数。此处提供更详细的示例。

回答by Cheeso

Is asynchronous programming akin to multi-threading?

异步编程类似于多线程吗?

Yes.

是的。

Javascript's asynch model provides a way to do work "in the background".

Javascript 的异步模型提供了一种“在后台”进行工作的方法。

Suppose you have a long-running calculation. This might be hard to imagine for a simple js demo, but imagine a long decompression routine, or a long-running pathfinding algorithm in a game, etc. some numerical calculation that takes more than a second.

假设您有一个长时间运行的计算。这对于一个简单的 js 演示来说可能很难想象,但想象一下一个很长的解压例程,或者一个游戏中长时间运行的寻路算法等等,一些需要超过一秒的数值计算。

Doing the calculation by directly invoking the function will work, but it will suspend the browser UI for the duration of the calculation. Running things asynchronously means the browser UI remains responsive, as the calculation continues running on a background thread. When the calc completes, according to the asynch programming pattern, the function invokes the callback function, notifying the application layer that the calculation is complete.

通过直接调用函数进行计算是可行的,但它会在计算期间暂停浏览器 UI。异步运行意味着浏览器 UI 保持响应,因为计算继续在后台线程上运行。当计算完成时,根据异步编程模式,该函数调用回调函数,通知应用层计算完成。