使用纯javascript异步将文本文件加载到字符串中

使用纯javascript异步将文本文件加载到字符串中,javascript,ajax,promise,async-await,xmlhttprequest,Javascript,Ajax,Promise,Async Await,Xmlhttprequest,在没有任何外部库的前端javascript应用程序中,我很难将文本文件加载到字符串中 xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", filename, true) xmlhttp.send() xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) myvariable = xmlhttp.responseText } 这段代

在没有任何外部库的前端javascript应用程序中,我很难将文本文件加载到字符串中

xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filename, true)
xmlhttp.send()

xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4)
        myvariable = xmlhttp.responseText
}
这段代码异步地将文本文件加载到变量中,但是当最终返回响应时,该变量仅在onreadystatechange块中可用。 任何试图将此变量获取到此范围之外的操作都会导致在返回响应之前执行代码,并且该变量始终未定义

function getFile(filename, callback) {

    xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", filename, true)
    xmlhttp.send()

    xmlhttp.onreadystatechange = function() {
         if (xmlhttp.readyState == 4)
            callback(xmlhttp.responseText)
    }
 }

function loadFile(filename) {
    var myString
    getFile(filename, function(reponseText){
        myString = responseText
    })
    return myString
}
一些人提出了这种模式来解决这个问题。然而,这确实提出了同样的问题,在提出这一点的大多数场景中,解决问题的方法是什么

async: false
我试图抽象掉文件加载过程,因为它将在我的代码中发生多次,并且可能会被修改多次。我希望将整个文件加载抽象为一个函数,我可以在代码中的任何地方调用该函数,而不必担心将代码嵌套在算法上不重要的IO任务的回调中。我还试图避免只使用同步请求。但在阅读了其他解决方案后,我不确定这是否可行

我正试图在没有任何外部库的纯javascript中实现这一点

xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filename, true)
xmlhttp.send()

xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4)
        myvariable = xmlhttp.responseText
}
编辑1/5/18

在尝试使用async/await和Promissions实现这一点之后,我遇到了非常类似的情况

function getFile(filename) {
    return new Promise(function(resolve, reject){   

        xmlhttp = new XMLHttpRequest()
        xmlhttp.open("GET", filename, true)
        xmlhttp.overrideMimeType("text/plain")
        xmlhttp.send()

        xmlhttp.onload = function() {
            if (xmlhttp.status == 200) {
                resolve(xmlhttp.responseText)
            }
            else {
                reject()
            }
        }
    })
}

async function loadFile(filename) {
    myfile = await getFile(filename)
    return myfile
}
调用loadFile()函数将返回解析为myfile值的承诺。然而,要获得该值,我们需要调用

loadFile().then(myfile => { /* Use my varible here */})
这使我处于完全相同的情况下,剩下的代码需要包装在由不重要的IO调用创建的函数中。奇怪的是,在声明为async的loadFile()函数中,如果我使用wait关键字,代码将同步运行,这是我试图在其余代码中获得的行为

async function loadFile(filename) {
    myfile = await getFile(filename)
    /* myfile is set here, like in syncronous code*/
    return myfile
    /* This returns a promise, getting us back to square 1*/
}
async/await语法似乎没有提供任何优于使用直接向上承诺的优势,我不得不手动构造一个承诺,而且我似乎正在将结果值直接解包并重新打包到另一个承诺中


我在这里遗漏了什么吗?

您可以将对象传递给loadFile函数并捕获fileResponse,如下所示:

    var fileObject = {
      fileResp: ''
    }

    function loadFile(filename, fileObject) {
        getFile(filename, function(reponseText){
            fileObject.fileResp = responseText
            triggerFileComplete()
        })
        return fileObject;
    }

   function triggerFileComplete() {
    // Do your next operation
    }

可能稍后或在triggerFileComplete中,您可以使用fileObject.fileResp

只要摆脱
loadFile()
并始终调用
getFile()
。或者使用承诺来代替回调,这是一种更稳健的现代方法。请看,JavaScript和浏览器API基本上是异步的。在这种情况下,像superagent或axios这样的小型请求库将为您节省大量的开发时间。另外,如果您不需要支持您认为可能的传统BurSersif,请查看使用更新的API,查看一下等待*/*AsiNC和/或承诺。否则,回调机制是一种常见的解决方案,因为文件加载器是异步的,我认为您无法编写(清理)异步工作的同步代码。查看了wait/async和Promises之后,异步函数似乎总是返回另一个promise(即使它没有返回值?)。“等待”来自异步函数的承诺的结果在该函数中提供了已解析承诺的值,但是不可能直接从异步函数返回该值?