gpt4 book ai didi

Why use callback in JavaScript, what are its advantages?(为什么在JavaScript中使用回调,它的优势是什么?)

转载 作者:bug小助手 更新时间:2023-10-25 12:46:19 29 4
gpt4 key购买 nike



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)




Could someone explain me this line with an example?

有谁能举个例子给我解释一下这行吗?


更多回答

A similar question has been asked here and a well explained answer too stackoverflow.com/questions/5485495/…

这里也提出了类似的问题,并给出了一个很好的解释,回答也是Stackoverflow.com/Questions/5485495/…

"but they could be implemented by using the normal functions" Please show me an asynchronous AJAX handler that handles the HTTP response without a callback function.

“但它们可以通过使用普通函数来实现”请向我展示一个不使用回调函数来处理HTTP响应的异步AJAX处理程序。

possible duplicate of How can I take advantage of callback functions for asynchronous XMLHttpRequest?

可能重复了如何利用异步XMLHttpRequest的回调函数?

@Tomalak Geret'kal: I think u misunderstood me. When I said "Typically, I found it being used in AJAX", I meant I found examples of AJAX that were using callback. I wanted other examples, besides AJAX where callbacks were needed. Also, in AJAX, how does the listening process goes on?

@Tomalak Geret‘kal:我想你误解了我的意思。当我说“通常,我发现它正在AJAX中使用”时,我的意思是我找到了使用回调的AJAX示例。除了需要回调的AJAX之外,我还想要其他例子。另外,在AJAX中,监听过程是如何进行的?

Also, in AJAX, how does the listening process goes on? How is the request being listened in parallel with the user making another request? (the link does not explain this).

在AJAX中,监听过程是如何进行的?如何在用户发出另一个请求的同时监听请求?(the这个链接没有解释)。

优秀答案推荐

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.

主浏览器进程是单线程事件循环。如果在单线程事件循环内执行长时间运行的操作,则进程会“阻塞”。这很糟糕,因为该进程在等待您的操作完成时停止处理其他事件。‘ert’是为数不多的阻止浏览器方法之一:如果您调用ert(‘test’),您将不能再点击链接、执行AJAX查询或与浏览器用户界面交互。



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();


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是单线程的,但您永远不会将该线程与等待捆绑在一起。如果您的JS线程很忙,那应该只是因为它正在活跃地运行代码。因此,即使JS是单线程的,对于您的代码来说,隐式地保存任意数量的任何类型的异步任务的状态也是微不足道的。



The synchronous method 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在其数据更改时进行回调。虽然不是严格意义上的异步,但您通常不会立即调用该回调。相反,它将在稍后被调用,以响应用户对事件的某种操作。



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.

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



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.

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



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 trigger and IE fireEvent methods) 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.

    具体地说,在JS中,事件分派的协调(例如,DOM DispatchEvent、jQuery触发器和IE FireEvent方法)没有指定(除了嵌套的DOM事件,它们是同步的)。如果触发了一个事件,处理程序可能会被延迟,并且执行会立即返回到触发器之后的任何位置。事件处理程序通常是同步调用的,但它们不需要这样做。


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

    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.sort takes a callback so you can define how elements are compared.

    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, prepend and wrap take 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、prepend和Wrap)接受回调,以基于jQuery方法提供的上下文构造元素。您可以将回调视为提供计算的内部部分或协调问题:当外部计算开始时,构建新DOM元素所需的数据不可用;当数据可用时,回调完成子计算以创建元素。



setTimeout and setInterval both take callbacks to execute after a delay.

SetTimeout和setInterval都接受延迟后执行的回调。



Starting with version 1.5, jQuery offers deferred objects as 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可以提供一种更有效的方法。一些控制结构(如协程)需要尾部调用,否则会出现堆栈溢出。



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

回调允许单线程操作(Java脚本是单线程)异步执行。




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 setTimeout or setInterval which 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.

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



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

由于您需要的不是AJAX的示例,因此异步特性的另一个常见用法是动画。动画需要回调,因为它需要允许绘制UI。



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

假设您想要在5秒内将一个div 100px向右移动。你的第一直觉可能会说,创造一个循环,然后在其间睡觉。但在Java脚本中没有休眠,即使有休眠,它也只会冻结用户界面,因为它在休眠时不会发生任何事情。



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

相反,您需要这样做:将位置递增10,然后使用回调调用setTimeout 500ms以执行下一帧。这可能会以递归方式完成。



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_function can be reused with a variety of functions used as callbacks, so sort of injecting code.

另一种用法只是简单地将函数作为参数传递,尽管我不确定术语“回调”是否适合该用例。这就是您在示例中使用它的方式,某些_Function可以与用作回调的各种函数一起重用,所以有点像是注入代码。



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 the name of a previously defined function as an argument of another function without any problem. And we can also pass the full code of an anonymous function as an argument too, e.g. in a XMLHttpRequest response handler for a form field validation process:

回调函数基本上是作为参数传递到另一个函数的调用中的函数(命名的或匿名的)。JavaScript语法允许我们将函数视为对象,因此我们可以将先前定义的函数的名称作为另一个函数的参数传递,而不会出现任何问题。我们还可以将匿名函数的完整代码作为参数传递,例如,在表单字段验证过程的XMLHttpRequest响应处理程序中:


req.onreadystatechange = () =>
{
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/lets/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/let/const/函数/集合,我们需要将这些函数的声明移到非回调函数的作用域中。这总是有点麻烦,有时甚至非常棘手。否则,我们可能需要重新定义非回调函数,以便将来自调用代码作用域的不可共享数据作为参数传递给它。当然,这会更改非回调函数的声明,并影响使用它的任何其他代码块。


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应用程序的前端,您将看到它们被用于事件侦听器之类的东西,例如,如果我们想要移除当我们将鼠标悬停在网页日历的“下一个月”箭头上时显示的鼠标悬停文本:


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

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

At the back end of web applications, 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.

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


Nowadays use of callback functions at the back end is seldom used as modern JavaScript includes a Promise object 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.

但知道它们是什么,以及它们可以在哪里得到有效利用,仍然是件好事。



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)每当您需要在第一个函数执行之后调用一个函数时,在这些场景中,我们需要使用回调。基本上,当我们需要将第一个函数的结果用于另一个函数时,回调的使用可以帮助我们,当然我们可以直接使用它,但如果第一个函数没有响应任何结果,并且我们已经将其传递给较低的函数,那么它将导致未定义的结果,稍后如果有人试图变异传递的值,它将导致错误,如无法变异或赋值为未定义。



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

除了回调之外,还应该使用承诺或异步/等待来使您的代码更模块化,看起来更像同步的方式



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 pushToDatabase function was called with the right data, so it can be refactored to:

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



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

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

callback(someData);
}


and called with handleData(someData, pushToDatabase).

并使用handleData(omeData,ushToDatabase)调用。



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);
});
});


Link to working Repl.

链接到工作代表。



There is two important aspect of using callback function in JavaScript.

在JavaScript中使用回调函数有两个重要方面。



  1. Asynchronous operation: Any function/task which takes some time to execute, callback ensures that it doesn't block the main thread and it keeps our page responsive and time taking task runs behind the scene. once it completed, we can use the result.



  2. Sequential operation: If we have more than one asynchronous operation and we want to execute it sequentially because result of one task determine other task's result.




This is what I understand about the callback. By keeping this two statement in mind, It might help to understand.

这就是我对回拨的理解。记住这两句话,可能会有助于理解。




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.

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


更多回答

I found this sentence from your answer most helpful: "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 answer was very helpful @EMI . I just have one query, is this possible to write link in terms of callback ? (see MakeNestedTree() in the link)

这个答案非常有用,@EMI。我只有一个问题,这可以写回调方面的链接吗?(参见链接中的MakeNestedTree())

Nicely explained.Thank you for sharing your knowledge.

解释得很好。谢谢你分享你的知识。

* Everyone must now do a shot.

*每个人现在都必须试一试。

@Harke it's used for similar purposes, however callbacks are less error prone than multi-threading. For instance you can never have race conditions or deadlocks in Javascript (although you can have infinite loops, which to the user is the same as a deadlock, but from a programmer standpoint is easier to debug).

@harke它用于类似的目的,但是回调比多线程更不容易出错。例如,在Java脚本中永远不会有争用条件或死锁(虽然您可以有无限循环,这对用户来说等同于死锁,但从程序员的角度来看更容易调试)。

The disadvantage of callbacks is that it requires a different mode of thinking than some programmers are used to (to be fair, so does correct multi-threading). You do also lose access to a proper stack trace when using callbacks because they're executed async.

回调的缺点是它需要与一些程序员习惯的不同的思维模式(公平地说,正确的多线程也是如此)。在使用回调时,您也无法访问正确的堆栈跟踪,因为它们是以异步方式执行的。

This is incorrect, Javascript is single-threaded so if you have a computationally intensive algorithm there's no way to do it "in the background". You can however break the calculation into chunks and call setTimeout(0, function () { /*next chunk of code */}); which would yield to the UI but isn't the same as simply throwing a calculation onto a background thread.

这是不正确的,Java脚本是单线程的,所以如果你有一个计算密集型的算法,就没有办法在“后台”完成它。但是,您可以将计算分成块并调用setTimeout(0,Function(){/*下一块代码*/});这将让位于UI,但不同于简单地将计算抛到后台线程上。

Here's an example that illustrates why this answer is incorrect. Using a setTimeout with a 10ms duration it asynchronously invokes a long_running_calc function that will take 5000ms to complete. Immediately after, it invokes another quick function in a setTimeout that delays the execution for 1000ms. The second function doesn't run after 1000ms, but instead it blocked until the long_running_calc is complete. This is due to the single-threaded nature of JavaScript. Web Workers are the only way to operate on a different thread.

这里有一个例子说明了为什么这个答案是不正确的。使用持续时间为10ms的setTimeout,它将异步调用一个long_running_calc函数,该函数需要5000毫秒才能完成。之后,它立即调用setTimeout中的另一个快速函数,将执行延迟1000ms。第二个函数在1000ms之后不运行,而是阻塞,直到long_running_calc完成。这是由于JavaScript的单线程特性造成的。网络工作者是在不同的线程上操作的唯一方式。

What you're describing is only possible with HTML5 web-workers, otherwise all asynchronous calculations are performed in the same thread as the main event loop.

您所描述的只有HTML5 Web工作器才能实现,否则所有的异步计算都会在与主事件循环相同的线程中执行。

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com