2017-01-15 3 views
0

Я работаю над приложением TVML/TVJS и столкнулся с проблемой при работе с классами в Javascript.Потеря доступа к функциям класса JS при выполнении обратного вызова

моей отправной 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 является глобальной переменной, определенной в приложении. js)

Все работает нормально в начале. Вызывается getHomeScreen(), ему удается вызвать getRemoteJSON() и передать _jsonLoaded() в качестве обратного вызова. getRemoteJSON выполняет вызов AJAX, а затем запускает обратный вызов. Именно здесь возникает проблема. Когда-то внутри _jsonLoaded, «this» становится неопределенным, поэтому, когда я вызываю this.getRemoteXMLFile, я получаю сообщение об ошибке «undefined не является объектом (оценка« this.getRemoteXMLFile »)»

Почему «это» работает в getHomeScreen(), но не в _jsonLoaded()? Как я могу получить доступ к моей функции getRemoteXMLFile из _jsonLoaded()?

Спасибо за любую помощь.

ответ

0

Это потому, что обратный вызов не является функцией.

Хорошим решением было бы использовать 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); 
    } 
); 
0

Почему "это" работает в getHomeScreen(), но не в _jsonLoaded ()? Как я могу получить доступ к моей функции getRemoteXMLFile из _jsonLoaded()?

Это технически не относится к TVML приложения, но более общий вопрос JS, так что позвольте мне не отвечать this (не каламбур) в свете JavaScript.

Когда вы вызываете getHomeScreen, вы вызываете его на экземпляр объекта resourceLoader.getHomeScreen(), и, следовательно, сохраняется контекст this. Но когда вы передаете функцию _jsonLoaded в качестве аргумента обратного вызова функции и делаем callback(template, xhr.responseText), контекст объекта теряется.

недавно представил JavaScript class ключевое слово might be confusing для кого-то с чистого языка OOP происхождения, так как это не является объектно-ориентированное наследование, а всего лишь синтаксический сахар вековой прототипных наследования в JavaScript. Поэтому, если кто-то входит в одну группу, рекомендуется понимать различия и gotchas.

Сказав это, одно прямое и простое решение для вашей оперативной задачи заключается в bind контексте this всякий раз, когда вы передаете функцию в качестве обратного вызова.

this.getRemoteJSON(homeData, homeTemplate, this._jsonLoaded.bind(this)); 

Side Примечание: Вы пробовали atvjs основу для построения TVML приложений? Он позволяет создавать и быстро создавать прототипы приложений без особого шума, абстрагируя основные сложности и сложности обычного приложения TVML.

Смежные вопросы