簡體   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