使用纯javascript

时间:2018-04-29 12:46:31

标签: 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
}

此代码将文本文件异步加载到变量中,但该变量仅在最终返回响应时在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中执行此操作。

编辑1/5/18

尝试使用async / await和Promises实现这一点后,我的情况非常相似。

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值的promise。但是要获得该值,我们需要调用

loadFile().then(myfile => { /* Use my varible here */})

这使我处于完全相同的情况,其中我的其余代码需要包含在由不重要的IO调用创建的函数中。关于这一点的奇怪之处在于,在声明为异步的loadFile()函数内部,如果我使用await关键字,代码会同步行为,这是我试图获取其余代码的行为。

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语法似乎没有提供任何优于使用直接承诺的优势,我不得不手动构建一个承诺,我似乎正在拆包并将结果值重新打包到另一个承诺中。

我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:0)

您可以将对象传递给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。