将数据从本地数据空间加载到异步操作的函数

时间:2017-02-28 22:19:41

标签: javascript asynchronous xmlhttprequest

我有一个不再有用的旧功能。根据控制台窗口,不再允许使用同步模式。我如何将其转换为使用异步模式并将数据传送出去?

var loadfile = function (filename, filetype) // Reads a file and returns it's contents as a string.
{filetype = filetype || 'text' // Assume text if no filetype is passed in
 var reader = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP"); // Provide a fallback for IE
     reader.responseType = filetype; // Prepare to read the proper type of data
     reader.open("GET", filename, false); // Target our local filename and prepare for synchronous read
     reader.send(); // Begin the read
 return reader.responseText; // Return the data as expected
};

我知道我可以通过删除第4行来强制执行此操作,但随后我会收到有关正在使用的折旧同步模式的XML错误和警告。警告可能会变得不再受支持'从现在开始几个月就会阻止程序运行的错误。

此外,我可以通过将第5行的false更改为true来切换到异步模式,但随后立即调用最后一行时,没有数据被传递出去。我可以让reader.onloadend()来处理数据,但是当我需要将它传递回loadfile()的调用者时,在那里调用的返回只是将读取数据转换为void。

因此,我被困住了。我在这里缺少什么?

编辑:在此处添加潜在的异步版本并指出它是如何工作的。

var loadfile = function (filename, filetype)
{var output = '';
 filetype = filetype || 'text';
 var reader = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP");
     reader.responseType = 'text';
     reader.open('GET', filename);
     reader.onloadend = function () {output = reader.responseText;}
     reader.send();
 while (output === '') {}
 return output;
};

当然,这有几个问题。首先,reader.onloadend()的范围使得它的输出副本与loadfile()中的副本分开。因此检索到的数据就会消失。我们可以返回它而不是将它分配给局部变量,但是onloadend会自动触发(如事件那样)并且返回的数据被发送到void中。不可恢复的。其次,即使我们可以在onloadend()函数中根据C ++中的引用来改变loadfile()的输出版本,等待输出变量改变的while循环也会(因为JavaScript是一个单进程线程)锁定系统,运行无限循环并且不允许发生任何更改。

Ergo,仍然卡住了。是的,我们可以输出到window.name或console.log或document.write,但这些选项都不允许loadfile()返回从XHMLHttpRequest / filename获取的数据。

此时我仍然坚持使用折旧的同步xhr和XML解析错误,因为我正在检索原始文本,而不是XML。

编辑SECUNDUS:我将脚本设置为默认为同步模式,并设法使错误无效(但不是关于使用折旧方法的初始警告...谢天谢地,在每次使用时都没有垃圾邮件警告)。不用说在这个函数上使用async / true不会让你到任何地方,但是async / false确实有用....现在。共享以防其他人需要此特定功能。

var loadfile = function (filename, async)
{if ("undefined" === typeof(async)) {async = false;}
 var reader = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP");
     reader.open('GET', filename, async);
     reader.onloadend = function () {return reader.responseText;}; // Lost to /dev/null while the program executes without this data.  Unacceptable!
     reader.overrideMimeType('text/plain');
     try
     {reader.send();}
     catch (e)
     {return null;}
 if (!async) {return reader.responseText;}
 //TODO: Find some way to delay execution without generating an infinite loop (good luck - javascript is not multithreaded so we cannot use a while loop for this)
 //TODO: Extract reader.responseText from within reader.onloadend() (probably by invoking a global temp object to shift the data out of onloadend()).
};

2 个答案:

答案 0 :(得分:0)

为了使您的功能更新,您应该将其封装到Promise中。这是一篇较旧的帖子解释:

How to promisify native XHR

使用回调

function makeRequest (method, url, done) {
  var xhr = new XMLHttpRequest();
  xhr.open(method, url);
  xhr.onload = function () {
    done(null, xhr.response);
  };
  xhr.onerror = function () {
    done(xhr.response);
  };
  xhr.send();
}

// And we'd call it as such:

makeRequest('GET', 'http://example.com', function (err, datums) {
  if (err) { throw err; }
  console.log(datums);
});

答案 1 :(得分:0)

Promise可以帮助您使异步代码更易于管理,但这不是必需的。

在您的情况下,您可以简单地使用事件侦听器。

var xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP");
xhr.responseType = 'text';
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.onload = function(){
    var res = JSON.parse(this.responseText);
    // do something with the response
    document.write('<h1>' + res.title + '</h1>');
    document.write('<p>' + res.body + '</p>');
}
xhr.send();

换句话说,您需要重构代码以消除调用返回某些东西的函数的需要(或者,简单地说,您的函数应该通过事件处理程序调用需要此xhr的其余代码)。

您可以详细了解XHR请求及其可能的结果,事件等。here