我是JavaScript新手。我找到了一个使用StackOverflow上的javascript打开本地文件的示例。进行一些谷歌搜索之后,我可以将Chrome设置为允许读取本地文件,然后可以运行该示例。但是,我想返回字符串allText
并在以后的脚本中使用它。但是字符串在undefined
之外变为readTextFile()
。
还有一个类似的问题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>
最佳答案
实际上,这很可能是范围问题。由于您异步设置allText,因此函数返回后将无法立即使用它。另外,您将在函数内重新初始化allText,这与返回的范围无关。
函数返回后,将执行rawFile.onreadystatechange
。您可以将执行移到XHR回调中,也可以将函数包装在promise中,这仍然需要您稍微修改控制流。
移动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>
承诺:
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 );
} );
这两种方法都将确保您的脚本在XHR请求返回之前不会尝试使用allText。
尽管正如Santiago Hernández所指出的,XHR请求是同步的,并且范围问题的性质与我最初设想的不同。问题在于在函数中重新声明变量,导致返回的变量未定义。