我正在尝试创建一个将文件名传递给构造函数的类,使用XmlHttpRequest加载文件,并将结果存储在类变量中。问题在于request.onreadystatechange
是一个异步函数,因此方法getData
在构造函数完成之前最终被调用。因此,数据的结果是不确定的。如何确保此类的方法在运行之前等待文件加载。我对异步代码和承诺并不陌生,所以请像我5岁时解释一下。
如我的代码所示,在超时中包装该方法可以解决该问题,但这是一个糟糕的解决方案,由于明显的性能问题,request.open
的同步版本已过时,因此不幸地,这也不是解决方案。
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script src="test.js"></script>
<script>
let test = new testClass('test.json')
console.log(test.getData)
</script>
</body>
</html>
class testClass {
constructor(filename) {
this.loaded_data = undefined
let request = new XMLHttpRequest()
request.overrideMimeType('application/json')
request.open('GET', filename)
request.onreadystatechange = () => {
if (request.status == '200' && request.readyState == 4) {
/* Load and parse JSON here */
this.loaded_data = 'foo'
}
}
request.send()
}
get getData() {
setTimeout(() => {
console.log(this.loaded_data)
}, 500);
return this.loaded_data
}
}
答案 0 :(得分:1)
从设计角度来看,文件本身不是“异步的”,异步加载该文件是什么。因此,您的类应该只代表一个已经加载的文件:
class File {
constructor(content) { this.content = content; }
现在加载该文件应该是静态的异步方法:
static load(path) {
return fetch(path) /*¹*/
.then(res => res.json())
.then(content => new File(content));
}
}
然后可以用作:
(async function() {
let file = await File.load('test.json')
console.log(file.content);
})()
¹:fetch()
比XmlHttpRequest更易于使用,因为它返回Promise(因此可以很好地与async
/ await
一起使用),并且提供了一些实用程序来解析/工作回应。在这种情况下,响应被解析为JSON。