如何利用异步XMLHttpRequest的回调函数?

时间:2022-09-29 23:11:26

I'm currently writing JavaScript and confusing about callback. I've found it's not kind of built-in functions though...
I'm now reading O'Relly JavaScript 5th Edition and it shows a sample code something like below:

我目前正在编写JavaScript并且对回调感到困惑。我发现它不是那种内置函数...我现在正在阅读O'Relly JavaScript第5版,它显示的示例代码如下所示:

getText = function(url, callback) // How can I use this callback?
{
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            callback(request.responseText); // Another callback here
        }
    }
    request.open('GET', url);
    request.send();
}

Basically, I suppose I don't understand the general idea of callback though... Could someone write a sample code to take advantage of callback above?

基本上,我想我不理解回调的一般概念......有人可以写一个示例代码来利用上面的回调吗?

4 个解决方案

#1


40  

Callbacks are pretty simple and nifty! Because of the nature of AJAX calls, you don't block execution of your script till your request is over (it would be synchronous then). A callback is simply a method designated to handle the response once it gets back to your method.

回调非常简单和漂亮!由于AJAX调用的性质,在请求结束之前,您不会阻止脚本的执行(这将是同步的)。回调只是一个指定处理响应的方法,一旦它返回到您的方法。

Since javascript methods are first class objects, you can pass them around like variables.

由于javascript方法是第一类对象,因此可以像变量一样传递它们。

So in your example

所以在你的例子中

getText = function(url, callback) // How can I use this callback?
{
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            callback(request.responseText); // Another callback here
        }
    }; 
    request.open('GET', url);
    request.send();
}

function mycallback(data) {
   alert(data);
}

getText('somephpfile.php', mycallback); //passing mycallback as a method

If you do the above, it means you pass mycallback as a method that handles your response (callback).

如果您执行上述操作,则表示您将mycallback作为处理响应(回调)的方法传递。

EDIT

编辑

While the example here doesn't illustrate the proper benefit of a callback (you could simply put the alert in the onReadyStateChange function after all!), re usability is certainly a factor.

虽然这里的示例没有说明回调的正确好处(您可以简单地将警报放在onReadyStateChange函数中!),但可重用性肯定是一个因素。

You have to keep in mind that the important thing here is that JS methods are first class objects. This means that you can pass them around like objects and attach them to all sorts of events. When events trigger, the methods attached to those events are called.

你必须记住,重要的是JS方法是第一类对象。这意味着您可以像对象一样传递它们并将它们附加到各种事件中。当事件触发时,将调用附加到这些事件的方法。

When you do request.onreadystatechange = function(){} you're just assigning that method to be called when the appropriate event fires.

当你执行request.onreadystatechange = function(){}时,你只是在适当的事件触发时分配要调用的方法。

So the cool thing here is that these methods can be reused. Say you have an error handling method that pops up an alert and populates some fields in the HTML page in the case of a 404 in the AJAX request.

所以这里很酷的是这些方法可以重复使用。假设您有一个错误处理方法,该方法会弹出警报并在AJAX请求中的404情况下填充HTML页面中的某些字段。

If you couldn't assign callbacks or pass methods as parameters, you'd have to write the error handling code over and over again, but instead all you have to do is just assign it as a callback and all your error handling will be sorted in one go.

如果你不能指定回调或传递方法作为参数,你必须一遍又一遍地编写错误处理代码,但是你只需要将它作为一个回调分配,你的所有错误处理都将被排序一气呵成。


#2


16  

First of all I would suggest reading up on what a callback is. Here is a start.

首先,我建议阅读回调的内容。这是一个开始。

The big picture

Callbacks are used extensively in asynchronous programming. When you don't want to block until a (possibly) long-running operation completes, one of the ways to approach the problem is to delegate the operation to someone who will do it on the side for you. This raises the question: how will you be able to tell when the operation is complete, and how will you get its results?

回调在异步编程中广泛使用。如果您不希望在(可能)长时间运行的操作完成之前阻塞,则解决问题的方法之一是将操作委派给将为您执行此操作的人员。这提出了一个问题:您将如何判断操作何时完成,以及如何获得结果?

One solution would be to delegate the work to someone else and take a moment off your normal work every now and then to ask "is the work I gave you done yet?". If so, get the results in some way and off you go. Problem solved.

一种解决方案是将工作委托给其他人,并且不时地从正常工作中抽出一些时间来问“我给你做的工作了吗?”。如果是这样,请以某种方式获得结果,然后离开。问题解决了。

The problem with this approach is that it doesn't make your life much easier. You are now forced to ask every little while and you will not know that the operation is done as soon as it actually is (but only the next time you remember to ask). If you forget to ask, you will never be notified.

这种方法的问题在于它不会让您的生活更轻松。你现在*每隔一段时间就会问一次,你不会知道操作是否一旦实际完成(但只有下次你记得要问)。如果您忘记提问,您将永远不会收到通知。

A better solution to this is the callback: when delegating work, provide a function along with it. The code which will actually do the work then promises to call that function as soon as the work completes. You can now forget all about that stuff and be secure in the knowledge that when the work is done, your callback will be called. No sooner, and no later.

更好的解决方案是回调:委派工作时,提供一个功能。实际完成工作的代码然后承诺在工作完成后立即调用该函数。您现在可以忘记所有这些内容,并且知道当工作完成后,您的回调将被调用。不久,不迟。

What is the callback here?

In this specific case, callback is a function that you provide to getText as a manner of allowing it to communicate with you. You are in effect saying "do this work for me, and when you are finished, here's a function for you to call to let me know".

在这种特定情况下,回调是一种函数,您可以将getText作为允许它与您通信的方式提供。你实际上在说“为我做这项工作,当你完成后,这里有一个功能让你打电话让我知道”。

getText in fact chooses to use this callback only when the XMLHttpRequest (XHR) is completed, and at the same time it "lets you know" it passes you the contents of the HTTP response as well (so you can act upon that information).

事实上,getText选择仅在XMLHttpRequest(XHR)完成时使用此回调,同时它“让你知道”它也会传递HTTP响应的内容(因此你可以对这些信息采取行动)。

Callbacks and more callbacks, oh my!

But take another moment to read the code. What is the value it stores to request.onreadystatechange? What is the purpose of request.onreadystatechange?

但是花点时间阅读代码。它为request.onreadystatechange存储的价值是多少? request.onreadystatechange的目的是什么?

The answer is that request.onreadystatechange is there for you to populate with a callback. In effect, XHR gives you a way to provide it with a callback, and it promises to "call you back" whenever the state of the underlying HTTP request changes.

答案是request.onreadystatechange可以用来填充回调。实际上,XHR为您提供了一种为其提供回调的方法,并且只要底层HTTP请求的状态发生变化,它就会“回拨”。

getText is a function that builds an abstraction on top of that: It plugs its own callback (an anonymous function -- I 'll refer to that as "inner") in there and accepts another callback from you (the parameter -- I 'll refer to it as "outer"). When the inner callback (which, remember: gets called whenever the state changes) detects that the state is "completed" (the meaning of the value 4) and the HTTP response status code is 200 (which means "OK"), it calls the outer callback to let you, the user of getText, know of the result.

getText是一个在其上构建抽象的函数:它在其中插入自己的回调(匿名函数 - 我将其称为“内部”)并接受来自您的另一个回调(参数 - 我'将其称为“外部”)。当内部回调(记住:每当状态改变时被调用)检测到状态为“已完成”(值为4的含义)并且HTTP响应状态代码为200(表示“OK”)时,它调用让你(getText的用户)知道结果的外部回调。

I hope I 'm making sense. :)

我希望我有道理。 :)

#3


1  

Me personally I prefer to use Event Listener over callbacks.

我个人更喜欢使用Event Listener而不是回调。

Using Listeners comes handy especially when You're willing to process multiple asynchronous requests at once.

使用Listener非常方便,尤其是当您愿意一次处理多个异步请求时。

The Usage is as follows (taken from https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest)

用法如下(取自https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest)

function reqListener () {
  console.log(this.responseText);
}

var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://www.example.org/example.txt");
oReq.send()

#4


0  

What works in a proper "callback" fashion is to define a service that returns a promise like this!

以正确的“回调”方式工作的是定义一个返回这样的承诺的服务!

$http.head("url2check").then(function () {
                return true;
            }, function () {
                return false;
            });

In the controller use the service:

在控制器中使用服务:

<service>.<service method>.then(function (found)) {
     if (found) {......
}

@jon is correct to call it Asynchronous!

@jon是正确的称它为异步!

#1


40  

Callbacks are pretty simple and nifty! Because of the nature of AJAX calls, you don't block execution of your script till your request is over (it would be synchronous then). A callback is simply a method designated to handle the response once it gets back to your method.

回调非常简单和漂亮!由于AJAX调用的性质,在请求结束之前,您不会阻止脚本的执行(这将是同步的)。回调只是一个指定处理响应的方法,一旦它返回到您的方法。

Since javascript methods are first class objects, you can pass them around like variables.

由于javascript方法是第一类对象,因此可以像变量一样传递它们。

So in your example

所以在你的例子中

getText = function(url, callback) // How can I use this callback?
{
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            callback(request.responseText); // Another callback here
        }
    }; 
    request.open('GET', url);
    request.send();
}

function mycallback(data) {
   alert(data);
}

getText('somephpfile.php', mycallback); //passing mycallback as a method

If you do the above, it means you pass mycallback as a method that handles your response (callback).

如果您执行上述操作,则表示您将mycallback作为处理响应(回调)的方法传递。

EDIT

编辑

While the example here doesn't illustrate the proper benefit of a callback (you could simply put the alert in the onReadyStateChange function after all!), re usability is certainly a factor.

虽然这里的示例没有说明回调的正确好处(您可以简单地将警报放在onReadyStateChange函数中!),但可重用性肯定是一个因素。

You have to keep in mind that the important thing here is that JS methods are first class objects. This means that you can pass them around like objects and attach them to all sorts of events. When events trigger, the methods attached to those events are called.

你必须记住,重要的是JS方法是第一类对象。这意味着您可以像对象一样传递它们并将它们附加到各种事件中。当事件触发时,将调用附加到这些事件的方法。

When you do request.onreadystatechange = function(){} you're just assigning that method to be called when the appropriate event fires.

当你执行request.onreadystatechange = function(){}时,你只是在适当的事件触发时分配要调用的方法。

So the cool thing here is that these methods can be reused. Say you have an error handling method that pops up an alert and populates some fields in the HTML page in the case of a 404 in the AJAX request.

所以这里很酷的是这些方法可以重复使用。假设您有一个错误处理方法,该方法会弹出警报并在AJAX请求中的404情况下填充HTML页面中的某些字段。

If you couldn't assign callbacks or pass methods as parameters, you'd have to write the error handling code over and over again, but instead all you have to do is just assign it as a callback and all your error handling will be sorted in one go.

如果你不能指定回调或传递方法作为参数,你必须一遍又一遍地编写错误处理代码,但是你只需要将它作为一个回调分配,你的所有错误处理都将被排序一气呵成。


#2


16  

First of all I would suggest reading up on what a callback is. Here is a start.

首先,我建议阅读回调的内容。这是一个开始。

The big picture

Callbacks are used extensively in asynchronous programming. When you don't want to block until a (possibly) long-running operation completes, one of the ways to approach the problem is to delegate the operation to someone who will do it on the side for you. This raises the question: how will you be able to tell when the operation is complete, and how will you get its results?

回调在异步编程中广泛使用。如果您不希望在(可能)长时间运行的操作完成之前阻塞,则解决问题的方法之一是将操作委派给将为您执行此操作的人员。这提出了一个问题:您将如何判断操作何时完成,以及如何获得结果?

One solution would be to delegate the work to someone else and take a moment off your normal work every now and then to ask "is the work I gave you done yet?". If so, get the results in some way and off you go. Problem solved.

一种解决方案是将工作委托给其他人,并且不时地从正常工作中抽出一些时间来问“我给你做的工作了吗?”。如果是这样,请以某种方式获得结果,然后离开。问题解决了。

The problem with this approach is that it doesn't make your life much easier. You are now forced to ask every little while and you will not know that the operation is done as soon as it actually is (but only the next time you remember to ask). If you forget to ask, you will never be notified.

这种方法的问题在于它不会让您的生活更轻松。你现在*每隔一段时间就会问一次,你不会知道操作是否一旦实际完成(但只有下次你记得要问)。如果您忘记提问,您将永远不会收到通知。

A better solution to this is the callback: when delegating work, provide a function along with it. The code which will actually do the work then promises to call that function as soon as the work completes. You can now forget all about that stuff and be secure in the knowledge that when the work is done, your callback will be called. No sooner, and no later.

更好的解决方案是回调:委派工作时,提供一个功能。实际完成工作的代码然后承诺在工作完成后立即调用该函数。您现在可以忘记所有这些内容,并且知道当工作完成后,您的回调将被调用。不久,不迟。

What is the callback here?

In this specific case, callback is a function that you provide to getText as a manner of allowing it to communicate with you. You are in effect saying "do this work for me, and when you are finished, here's a function for you to call to let me know".

在这种特定情况下,回调是一种函数,您可以将getText作为允许它与您通信的方式提供。你实际上在说“为我做这项工作,当你完成后,这里有一个功能让你打电话让我知道”。

getText in fact chooses to use this callback only when the XMLHttpRequest (XHR) is completed, and at the same time it "lets you know" it passes you the contents of the HTTP response as well (so you can act upon that information).

事实上,getText选择仅在XMLHttpRequest(XHR)完成时使用此回调,同时它“让你知道”它也会传递HTTP响应的内容(因此你可以对这些信息采取行动)。

Callbacks and more callbacks, oh my!

But take another moment to read the code. What is the value it stores to request.onreadystatechange? What is the purpose of request.onreadystatechange?

但是花点时间阅读代码。它为request.onreadystatechange存储的价值是多少? request.onreadystatechange的目的是什么?

The answer is that request.onreadystatechange is there for you to populate with a callback. In effect, XHR gives you a way to provide it with a callback, and it promises to "call you back" whenever the state of the underlying HTTP request changes.

答案是request.onreadystatechange可以用来填充回调。实际上,XHR为您提供了一种为其提供回调的方法,并且只要底层HTTP请求的状态发生变化,它就会“回拨”。

getText is a function that builds an abstraction on top of that: It plugs its own callback (an anonymous function -- I 'll refer to that as "inner") in there and accepts another callback from you (the parameter -- I 'll refer to it as "outer"). When the inner callback (which, remember: gets called whenever the state changes) detects that the state is "completed" (the meaning of the value 4) and the HTTP response status code is 200 (which means "OK"), it calls the outer callback to let you, the user of getText, know of the result.

getText是一个在其上构建抽象的函数:它在其中插入自己的回调(匿名函数 - 我将其称为“内部”)并接受来自您的另一个回调(参数 - 我'将其称为“外部”)。当内部回调(记住:每当状态改变时被调用)检测到状态为“已完成”(值为4的含义)并且HTTP响应状态代码为200(表示“OK”)时,它调用让你(getText的用户)知道结果的外部回调。

I hope I 'm making sense. :)

我希望我有道理。 :)

#3


1  

Me personally I prefer to use Event Listener over callbacks.

我个人更喜欢使用Event Listener而不是回调。

Using Listeners comes handy especially when You're willing to process multiple asynchronous requests at once.

使用Listener非常方便,尤其是当您愿意一次处理多个异步请求时。

The Usage is as follows (taken from https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest)

用法如下(取自https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest)

function reqListener () {
  console.log(this.responseText);
}

var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://www.example.org/example.txt");
oReq.send()

#4


0  

What works in a proper "callback" fashion is to define a service that returns a promise like this!

以正确的“回调”方式工作的是定义一个返回这样的承诺的服务!

$http.head("url2check").then(function () {
                return true;
            }, function () {
                return false;
            });

In the controller use the service:

在控制器中使用服务:

<service>.<service method>.then(function (found)) {
     if (found) {......
}

@jon is correct to call it Asynchronous!

@jon是正确的称它为异步!