运行回调时无法访问 JS 类中的函数
Posted
技术标签:
【中文标题】运行回调时无法访问 JS 类中的函数【英文标题】:Losing access to functions within a JS class when running a callback 【发布时间】:2017-01-15 15:58:16 【问题描述】:我正在开发一个 TVML/TVJS 应用程序,并且在使用 javascript 中的类时遇到了问题。
我的起始 application.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 时,我收到错误消息“未定义不是对象(正在评估 'this.getRemoteXMLFile')”
为什么“this”在 getHomeScreen() 中有效,但在 _jsonLoaded() 中无效?如何从 _jsonLoaded() 访问我的 getRemoteXMLFile 函数?
感谢您的帮助。
【问题讨论】:
【参考方案1】:那是因为回调不是一个函数。
一个好的解决方案是使用 ES6 Promises。
这是一个使用带有 Promise 的 AJAX 获取数据的示例
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);
);
【讨论】:
【参考方案2】:为什么“this”在 getHomeScreen() 中有效,但在 _jsonLoaded() 中无效?如何从 _jsonLoaded() 访问我的 getRemoteXMLFile 函数?
这在技术上并不特定于 TVML 应用程序,而是更多的一般 JS 问题,所以让我根据 JavaScript 回答 this
(不是双关语)。
当您调用 getHomeScreen
时,您会在对象实例 resourceLoader.getHomeScreen()
上调用它,因此会保留 this
上下文。但是当你将_jsonLoaded
函数作为函数的回调参数传递并执行callback(template, xhr.responseText)
时,对象上下文就丢失了。
最近为具有纯 OOP 语言背景的人引入了 JavaScript class
关键字 might be confusing,因为它不是面向对象的继承,而仅仅是 JavaScript 中古老的原型继承的语法糖。因此,如果碰巧属于同一组,建议了解差异并gotchas。
话虽如此,当您将函数作为回调传递时,一个直接而简单的解决方案就是在bind
this
上下文中处理您的直接问题陈述。
this.getRemoteJSON(homeData, homeTemplate, this._jsonLoaded.bind(this));
旁注:您是否尝试过 atvjs 框架来构建 TVML 应用程序?它可以让您在没有太多噪音的情况下构建和快速原型化应用程序,从而抽象出传统 TVML 应用程序的底层麻烦和复杂性。
【讨论】:
以上是关于运行回调时无法访问 JS 类中的函数的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 node.js 运行时访问 Azure Function App 函数中的 multipart/form-data