[英]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.