2016-08-04 139 views
2

我是JavaScript新手。我找到了一個使用javascript在StackOverflow上打開本地文件的示例。在Google搜索之後,我可以將我的Chrome設置爲允許讀取本地文件,然後我就可以運行該示例。但是,我想返回字符串allText,稍後在我的腳本中使用它。但字符串在readTextFile()之外變成undefined在JavaScript中打開本地文件

還有一個類似的問題here。這似乎與AJAX的異步功能有關。我現在幾乎無法理解這些行話。我只是不明白爲什麼在這篇文章中XMLHttpRequest.open()的第三個參數設置爲true

無論如何,下面是我目前的代碼。我想使用allText外部函數readTextFile()

<!DOCTYPE html> 
<html> 
    <script> 
     function readTextFile(file) 
     { 
      var allText; 
      var rawFile = new XMLHttpRequest(); 
      rawFile.open("GET", file, false); 
      rawFile.onreadystatechange = function() 
      { 
       if(rawFile.readyState === 4) 
       { 
        if(rawFile.status === 200 || rawFile.status == 0) 
        { 
         var allText = rawFile.responseText; 
         alert(allText); 
        } 
       } 
      } 
      rawFile.send(null); 
      return allText; // this is the part that goes wrong I think 
     } 

     t = readTextFile("foo.file"); 
     document.write(t) // print out "undeifned" instead of the correct answer 

    </script> 
</html> 
+0

可能的重複[如何返回來自異步調用的響應?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-調用) – Marty

+2

你聲明'allText'兩次(使兩個變量具有相同的名稱但不同的範圍),刪除變量之前的第二個'var'關鍵字。祝你好運! –

+0

@SantiagoHernández這是它的一部分,但它仍然不能解決異步履行競爭條件,並且在XHR請求完成之前它仍然是未定義的。 –

回答

3

這實際上很可能是範圍問題。因爲您正在異步設置所有文本,所以在函數返回後不可立即使用。另外,你正在重新初始化一個函數中的所有文本,這與返回的範圍無關。

rawFile.onreadystatechange在函數返回後執行。您可以將執行過程移至XHR回調函數中,也可以將函數包裝在承諾中,這仍然需要您修改控制流程。

移動document.write

<!DOCTYPE html> 
<html> 
    <script> 
     function readTextFile(file) 
     { 
      var allText; 
      var rawFile = new XMLHttpRequest(); 
      rawFile.open("GET", file); 
      rawFile.onreadystatechange = function() 
      { 
       if(rawFile.readyState === 4) 
       { 
        if(rawFile.status === 200 || rawFile.status == 0) 
        { 
         allText = rawFile.responseText; 
         document.write(allText); 
        } 
       } 
      } 
      rawFile.send(null); 
     } 

     readTextFile("foo.file"); 

    </script> 
</html> 

Promisified:

function readTextFile(file) { 
    return new Promise(function (fulfill, reject) { 

    var allText; 
    var rawFile = new XMLHttpRequest(); 
    rawFile.open("GET", file); 
    rawFile.onreadystatechange = function() { 
     if (rawFile.readyState === 4) { 
     if (rawFile.status === 200 || rawFile.status == 0) { 
      fulfill(rawFile.responseText) 
     } 
     } 
    } 
    rawFile.send(null); 
    }); 
} 
readTextFile("foo.file") 
    .then(function (t) { 
    document.write(t); 
    }); 

這兩項將確保您的腳本不嘗試使用allText直到它被XHR返回請求。

儘管Santiago Hernández指出,XHR請求是同步的,範圍問題與我第一次假設的性質不同。問題在於重新聲明函數中的變量,導致返回的變量未定義。

+2

實際上'allText'正在同步設置,阻塞主線程......並且它在'rawFile.onreadystatechange'完成後完全可訪問 –

+1

是!我的錯。最初,我沒有注意到XHR請求上的異步「false」標誌。信貸在哪裏到期,你有正確的答案:) –

+2

沒問題:) ..順便說一句,回調地獄是真正的地獄 –