我正在开发TVML/TVJS应用程序,在使用Javascript中的类时遇到了问题。
我的启动应用程序.js文件调用一个函数
resourceLoader = new ResourceLoader();
resourceLoader.getHomeScreen();
我有一个名为ResourceLoader.js的单独文件,其中包含以下内容:
class ResourceLoader {
getHomeScreen() {
var homeData = BASEURL + "/home.json";
var homeTemplate = BASEURL + "/home.tvml";
this.getRemoteJSON(homeData, homeTemplate, this._jsonLoaded);
}
_jsonLoaded(template, jsonString) {
var parsedJSON = JSON.parse(jsonString);
this.getRemoteXMLFile(template, parsedJSON);
}
getRemoteJSON(file, template, callback) {
var xhr = new XMLHttpRequest();
xhr.responseType = "text";
xhr.addEventListener("load", function() {
callback(template, xhr.responseText);
}, false);
xhr.open("GET", file, true);
xhr.send();
}
getRemoteXMLFile(template, json) {
var xhr = new XMLHttpRequest();
xhr.responseType = "xml";
xhr.addEventListener("load", function() {
loadRemoteFile(xhr.responseText, json);
}, false);
xhr.open("GET", template, true);
xhr.send();
}
}
(BASEURL是application.js中定义的全局变量)
一开始一切都很好。调用getHomeScreen()时,它设法调用getRemoteJSON()并将_jsonLoaded()作为回调传递。getRemoteJSON执行AJAX调用,然后运行回调。这就是问题发生的地方。一旦进入_jsonLoaded,"this"就会变成未定义的,所以当我调用this.getRemoteXMLFile时,我会得到错误消息"undefined不是对象(正在评估"this.getRemoteXMLFile")">
为什么"this"在getHomeScreen()中有效,而在_jsonLoaded()中无效?如何从_jsonLoaded()访问getRemoteXMLFile函数?
谢谢你的帮助。
一个好的解决方案是使用ES6 Promises。
下面是一个使用AJAX和Promise 获取数据的示例
getJson(url) {
return new Promise(
(resolve, reject) => {
this.get(url).then(
(value) => {
resolve(JSON.parse(value));
},
function (reason) {
console.error(reason);
reject(new Error(reason));
}
)
}
)
}
以及如何将其称为
getJson('http://jsonplaceholder.typicode.com/posts/1').then(
(value) => {
console.log(value);
},
function (reason) {
console.error(reason);
}
);
为什么"this"在getHomeScreen()中有效,而在_jsonLoaded()中无效?如何从_jsonLoaded()访问getRemoteXMLFile函数?
从技术上讲,它不是TVML应用程序特有的,而是一个通用的JS问题,所以让我根据JavaScript回答this
(并非双关语)。
当您调用getHomeScreen
时,您会在对象实例resourceLoader.getHomeScreen()
上调用它,因此会保留this
上下文。但是,当您将_jsonLoaded
函数作为函数的回调参数传递并执行callback(template, xhr.responseText)
时,对象上下文将丢失。
最近引入的JavaScriptclass
关键字可能会让具有纯OOP语言背景的人感到困惑,因为它不是面向对象的继承,而只是JavaScript中古老原型继承的语法糖。因此,如果一个人碰巧属于同一个群体,最好了解其中的差异和陷阱。
话虽如此,对于您的直接问题语句,一个直接而简单的解决方案是,每当您将函数作为回调传递时,都要bind
this
上下文。
this.getRemoteJSON(homeData, homeTemplate, this._jsonLoaded.bind(this));
旁注:您是否尝试过构建TVML应用程序的atvjs框架?它可以让你在没有太多噪音的情况下构建并快速原型化应用程序,抽象出传统TVML应用程序的潜在麻烦和复杂性