繁体   English   中英

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

[英]How can I take advantage of callback functions for asynchronous XMLHttpRequest?

我目前正在编写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();
}

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

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

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

所以在你的例子中

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

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

编辑

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

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

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

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

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


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

大局

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

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

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

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

这里的回调是什么?

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

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

回调和更多的回调,哦,我的!

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

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

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

我希望我有道理。 :)

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

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

用法如下(摘自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()

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

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

在控制器中使用服务:

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

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

XMLHttpRequest回调函数和文件上传数据数组

function HttpPost(url, arr, cb, form){
    if (form === undefined) { var data = new FormData(); }else{ var data = new FormData(form); }
    if (arr !== undefined) {
        for (const index in arr) {    
            data.append(index, arr[index]);
        }
    }
    var hr = new XMLHttpRequest();        
    hr.onreadystatechange=function(){
        if (hr.readyState==4 && hr.status==200){
            if( typeof cb === 'function' ){ cb(hr.responseText); }
        }
    }
    hr.upload.onprogress = function(e) {
        var done = e.position || e.loaded, total = e.totalSize || e.total;
        console.log('xhr.upload progress: ' + done + ' / ' + total + ' = ' + (Math.floor(done/total*1000)/10) + '%');
    };
    hr.open("POST",url,true);
    hr.send(data);
}

// HttpPost callback
function cb_list(res){
    console.log(res);
    var json = JSON.parse(res);
    console.log(json.id + ' ' + json.list);
    // loop
    for (var objindex in json.list){
        console.log(json.list[objindex].id);
    }
}

样品:

var data = [];
data["cmd"] = "get-cos";
var form = $('#form')[0];

HttpPost('/api-load', data, cb_list, form);

<form id="form" method="POST" enctype="multipart/form-data">
    <input type="file" name="file[]" multiple accept="image/*">
</form>

Http标题内容

hr.setRequestHeader("Content-Type", "application/json"); 
// data:
var json = {"email": "hey@mail.xx", "password": "101010"}
var data = JSON.stringify(json);

hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// data: 
var data = "fname=Henry&lname=Ford";

暂无
暂无

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

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