【问题标题】:Losing access to functions within a JS class when running a callback运行回调时无法访问 JS 类中的函数
【发布时间】: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 函数?

感谢您的帮助。

【问题讨论】:

    标签: javascript class tvml tvjs


    【解决方案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 应用程序的底层麻烦和复杂性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-04
        相关资源
        最近更新 更多