2016-09-01 13 views
2

我有一個文件,tst.html與內容:JavaScript(Vanilla,no jQuery) - 具有* synchronous的函數* AJAX(XMLHttpRequest)調用的行爲與async相同?

part two 

(無標記或其他任何東西,只是爲了演示)

,然後加載所述文件,通過同步 AJAX( XMLHttpRequest):

function someFunc() { 
    var str = 'part one_'; 

    var x = new XMLHttpRequest(); 
    x.open('GET', 'tst.html', false); // "false" for synchronous 
    x.onreadystatechange = function() { 
     if(x.readyState === 4) { 
      switch(x.status) { 
       case 200: 
        str += x.responseText.trim(); 
        break; 

       default: 
        return ''; // Or something 
        break; 
      } 
     } 
    } 
    x.send(); 

    str += '_part three'; 

    return str; 
} 

調用好玩ction:

alert(someFunc()); 

// Returns "part one_part two_part three" 

這是所需的行爲。

但如果我把AJAX調用到它自己的功能:

function ajaxCall() { 
    var x = new XMLHttpRequest(); 
    x.open('GET', 'tst.html', false); 
    x.onreadystatechange = function() { 
     if(x.readyState === 4) { 
      switch(x.status) { 
       case 200: 
        return x.responseText.trim(); 
        break; 

       default: 
        return ''; 
        break; 
      } 
     } 
    } 

    x.send(); 
} 

function someFunc() { 
    var str = 'part one'; 

    str += ajaxCall(); 

    str += 'part three'; 

    return str; 
} 

然後調用它:

alert(someFunc()); 

// Returns "part one_undefined_part three" 

函數返回聯軍字符串AJAX有機會完成之前,這與其異步表兄弟的行爲相同。

我一直在尋找沿着「同步AJAX功能」的東西,但是沒有任何東西可以用於任何用途。

AJAX調用的最終用例位於函數的遞歸集合內部,其進一步處理依賴於AJAX返回。類似:

function one(url) { 
    var x = new XMLHttpRequest(); 
    x.open('GET', url, false); 
    x.onreadystatechange = function() { 
     return two(x.responseText.trim()); 
    } 
    x.send(); 
} 

function two(str) { 
    var output; 

    output += stuff; 

    // ... parse through str 
    // ... until match found 

    if(isURL(match)) {      // If `match` is a URL 
     output += one(match); 
    }else if(isFormattedString(match)) { // if `match` is a string 
     output += two(match); 
    } 

    output += more stuff; 

    // More processing of output  

    return output; 
} 

var final = one(url); 

在上面的例子:

  • 系統總是與URL啓動(one(url)
  • one()返回一個字符串,其本身爲two(str)
  • 開口參數
  • two()內,解析器可能遇到以下任一種:

    1. 另一個URL或

    2. 一個可解析的字符串。

  • 取決於哪個是,兩個功能中的一個被稱爲

  • 的輸出被添加到系統中的最終結果

one()從一個回調將不起作用在這一點上,因爲我仍然需要在two()之內有最後的return

function one(url, callback) { 
    // ... AJAX stuff 
    { 
     callback(two(x.responseText)); 
    } 
} 

function two(str) { 
    // ... same as previous 

    // The following doesn't work, because then `two()` no longer has a `return` 
    // ... and any other code (i.e. for !isURL cases) will still continue to execute 
    if(isURL(match)) { 
     one(match, function(result) { 
      output += result; 

      // ... more processing 

      return output; 
     }); 
    }else if(...) { 
     // ... same as previous 
    } 

    // ... more stuffs 
} 

我發現的唯一的另一件事是deferred,但我不能確定它如何與這個工作,要麼。

有沒有一種方法可以強制JavaScript像對待其他同步函數一樣對待它,其中執行代碼會停止,直到函數完成爲止?我不清楚它爲什麼還沒有,AJAX請求特別聲明爲異步。

在此先感謝。

+3

你的函數'ajaxCall'不返回任何東西 - 相當於'return undefined' - 你需要從函數返回一些東西(不是onreadystate回調) –

+0

同步ajax調用真的不是一個好主意 - 如果服務器有問題會怎樣? JavaScript線程將等待直到服務器響應,並且頁面將完全不響應用戶。同步ajax永遠不會有好的例子。不要使用它。 – Simba

+0

我會建議嘗試使用「承諾」(整潔的東西)。在Jamiec的回答中發佈的鏈接中給出了一個簡要的解釋,否則在MDN中查看:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise – Winter

回答

6

我喜歡你的長,具體的問題(!希望大家把儘可能多的精力投入到問),但在本質上它歸結爲:

function ajaxCall() { 
    var x = new XMLHttpRequest(); 
    x.open('GET', 'tst.html', false); 
    x.onreadystatechange = function() { 
     if(x.readyState === 4) { 
      switch(x.status) { 
       case 200: 
        return x.responseText.trim(); 
        break; 

       default: 
        return ''; 
        break; 
      } 
     } 
    } 

    x.send(); 
} 

return語句是從onreadystatechange回報,不ajaxCall如你所料。它不同於你的原始版本,因爲你的原始文件只是連接字符串。它與將其轉移到自己的功能無關。

不使用同步ajax!瞭解異步函數的工作方式,尤其是How do I return the response from an asynchronous call?

1

的問題是,你從處理程序return

return x.responseText.trim(); 

回報,但不能從ajaxCall功能 - 它沒有return語句,所以總是返回undefined