通过TVJS-tvOS消费API JSon调用



我正在尝试玩tvOS,我有一个关于处理json调用的小问题。我需要通过API获取一些数据,假设为了测试,我调用这个链接

http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%223015%22&format=json

我试着用这个函数做一些修改

function getDocument(url) {
  var templateXHR = new XMLHttpRequest();
  templateXHR.responseType = "json";
  templateXHR.open("GET", url, true);
  templateXHR.send();
  return templateXHR;
}

但没有成功。有什么提示或帮助吗?

如果我需要使用NodeJS,我该怎么做呢?

这是我得到的工作。它在许多方面都不理想,但向您展示了一些开始的东西。

function jsonRequest(options) {
  var url = options.url;
  var method = options.method || 'GET';
  var headers = options.headers || {} ;
  var body = options.body || '';
  var callback = options.callback || function(err, data) {
    console.error("options.callback was missing for this request");
  };
  if (!url) {
    throw 'loadURL requires a url argument';
  }
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'json';
  xhr.onreadystatechange = function() {
    try {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          callback(null, JSON.parse(xhr.responseText));
        } else {
          callback(new Error("Error [" + xhr.status + "] making http request: " + url));
        }
      }
    } catch (err) {
      console.error('Aborting request ' + url + '. Error: ' + err);
      xhr.abort();
      callback(new Error("Error making request to: " + url + " error: " + err));
    }
  };
  xhr.open(method, url, true);
  Object.keys(headers).forEach(function(key) {
    xhr.setRequestHeader(key, headers[key]);
  });
  xhr.send();
  return xhr;
}

你可以用下面的例子调用它:

jsonRequest({
  url: 'https://api.github.com/users/staxmanade/repos',
  callback: function(err, data) {
    console.log(JSON.stringify(data[0], null, ' '));
  }
});

我在tvOS上测试了这个-与jQuery的语法一起工作(基本测试通过):

var $ = {};
$.ajax = function(options) {
  var url = options.url;
  var type = options.type || 'GET';
  var headers = options.headers || {} ;
  var body = options.data || null;
  var timeout = options.timeout || null;
  var success = options.success || function(err, data) {
    console.log("options.success was missing for this request");
  };
  var contentType = options.contentType || 'application/json';
  var error = options.error || function(err, data) {
    console.log("options.error was missing for this request");
  };
  if (!url) {
    throw 'loadURL requires a url argument';
  }
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'json';
  xhr.timeout = timeout;
  xhr.onreadystatechange = function() {
    try {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            if (xhr.responseType === 'json') {
                success(null, xhr.response);
            } else {
                success(null, JSON.parse(xhr.responseText));
            }
        } else {
          success(new Error("Error [" + xhr.status + "] making http request: " + url));
        }
      }
    } catch (err) {
      console.error('Aborting request ' + url + '. Error: ' + err);
      xhr.abort();
      error(new Error("Error making request to: " + url + " error: " + err));
    }
  };
  xhr.open(type, url, true);
  xhr.setRequestHeader("Content-Type", contentType);
  xhr.setRequestHeader("Accept", 'application/json, text/javascript, */*');
  Object.keys(headers).forEach(function(key) {
    xhr.setRequestHeader(key, headers[key]);
  });
  if(!body) {
    xhr.send();
    } else {
        xhr.send(body);
    }
  return xhr;
}

在Apple TV上运行的示例查询:

var testPut = function(){
    $.ajax({
        type: 'PUT',
        url: url,
        success: successFunc,
        error: errFunc,
        dataType: 'json',
        contentType: 'application/json',
        data: data2
    });
}
var testGet = function(){
    $.ajax({
        dataType: 'json',
        url: url,
        success: successFunc,
        error: errFunc,
        timeout: 2000
    });
}
var getLarge = function(){
    $.ajax({
        dataType: 'json',
        url: url,
        success: successFunc,
        error: errFunc,
        timeout: 2000
    });
}

你是否在'App.onLaunch'中调用了你的函数

App.onLaunch = function(options) {
  var url = 'http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%223015%22&format=json';
  var doc = getDocument(url);
  console.log(doc);
}

可能值得一看https://mathiasbynens.be/notes/xhr-responsetype-json

我遇到了这个问题,希望完成同样的事情,并受到@JasonJerrett的回答的启发,但发现它有点缺乏,因为在我的实例中,我使用的是Javascript内置的XML模板,像这样:

// Index.xml.js
var Template = function() { 
  return `very long xml string`;
};

问题是不能在模板本身内执行XHR请求,因为模板字符串将在XHR请求实际完成之前返回(无法从异步回调内部返回数据)。我的解决方案是在调用模板并将数据传递给模板函数之前,修改资源加载器并在中执行XHR请求:

ResourceLoader.prototype.loadResource = function(resource, dataEndpoint, callback) {
    var self = this;
    evaluateScripts([resource], function(success) {
        if (success) {
            // Here's the magic. Perform the API call and once it's complete,
            // call template constructor and pass in API data
            self.getJSON(dataEndpoint, function(data) {
                var resource = Template.call(self, data);
                callback.call(self, resource);
            });
        } else {
            var title = "Failed to load resources",
                description = `There was an error attempting to load the resource. nn Please try again later.`,
                alert = createAlert(title, description);
            Presenter.removeLoadingIndicator();
            navigationDocument.presentModal(alert);
        }
    });
}
// From: https://mathiasbynens.be/notes/xhr-responsetype-json
ResourceLoader.prototype.getJSON = function(url, successHandler, errorHandler) {
  var xhr = new XMLHttpRequest();
  xhr.open('get', url, true);
  xhr.onreadystatechange = function() {
    var status;
    var data;
    if (xhr.readyState == 4) { 
      status = xhr.status;
      if (status == 200) {
        data = JSON.parse(xhr.responseText);
        successHandler && successHandler(data);
      } else {
        errorHandler && errorHandler(status);
      }
    }
  };
  xhr.send();
};

然后需要修改模板函数以接受传入的API数据作为参数:

// Index.xml.js
var Template = function(data) { 
    return 'really long xml string with injected ${data}';
};

您需要在XHR对象上实现onreadystatechange事件来处理响应:

templateXHR.onreadystatechange = function() {
  var status;
  var data;
  if (templateXHR.readyState == 4) { //request finished and response is ready
    status = templateXHR.status;
    if (status == 200) {
      data = JSON.parse(templateXHR.responseText);
      // pass the data to a handler
    } else {
      // handle the error
    }
  }
};

如果你想在应用启动时调用请求,只需添加application.js:

App.onLaunch = function(options) {
  var javascriptFiles = [
    `${options.BASEURL}js/resourceLoader.js`, 
    `${options.BASEURL}js/presenter.js`
  ];
evaluateScripts(javascriptFiles, function(success) {
 if(success) {
  resourceLoader = new ResourceLoader(options.BASEURL);
  var index = resourceLoader.loadResource(`${options.BASEURL}templates/weatherTemplate.xml.js`, function(resource) {
    var doc = Presenter.makeDocument(resource);
    doc.addEventListener("select", Presenter.load.bind(Presenter));
    doc.addEventListener('load', Presenter.request);
    navigationDocument.pushDocument(doc);
  });
} else {
  var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
  navigationDocument.presentModal(errorDoc);
}

});}

在present .js中添加一个方法:

request: function() {
  var xmlhttp = new XMLHttpRequest() , method = 'GET' , url = 'your Api url';
  xmlhttp.open( method , url , true );
  xmlhttp.onreadystatechange = function () {
    var status;
    var data;
    if (xmlhttp.readyState == 4) {
      status = xmlhttp.status;
      if (status == 200) {
        data = JSON.parse(xmlhttp.responseText);
        console.log(data);
      } else {
        var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
        navigationDocument.presentModal(errorDoc);
      }
    }
  };
  xmlhttp.send();
},

最新更新