我有一个不再有用的旧功能。根据控制台窗口,不再允许使用同步模式。我如何将其转换为使用异步模式并将数据传送出去?
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()).
};
答案 0 :(得分:0)
为了使您的功能更新,您应该将其封装到Promise中。这是一篇较旧的帖子解释:
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。