如何延迟执行javascript函数,直到加载JSON

时间:2016-04-07 07:22:59

标签: javascript json ajax promise

我有一个链接两个API调用的页面,在执行myWebView.delegate = self 函数之前将数据加载到first_datasecond_data(这是几kb的数据操作和d3.js) :

template.html

createPage

问题在于,操纵<script src="createPage.js"></script> <script> var first_data, second_data = [], []; function getFirstData(){ return new Promise(function(resolve) { var xhr = new XMLHttpRequest(); var url = "/API/my-request?format=json" xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { first_data = JSON.parse(xhr.responseText); resolve('1'); } } xhr.open("GET", url, true); xhr.send(); }); } //similar function for getSecondData() getFirstData() .then(getSecondData) .then(createPage(first_data, second_data)); </script> 中数据的某些代码显示错误,例如“createPage”。在那个特定错误的情况下,这是因为我尝试对应该从API请求加载的一些数据执行can't convert undefined to object。一些观察:

  • 如果我在浏览器开发控制台中检查数据,它就在那里。
  • 如果我只是在控制台中粘贴文件中的代码,那么页面就可以了。
  • 如果我为代码的数据操作部分硬编码初始化数组等(为了摆脱Object.keys(data[0]),那么页面绘制,但所有图形表明它们没有数据填充。< / LI>
  • 如果我将JSON数据放在.js文件中并将其作为脚本加载到正文末尾的createPage.js文件之前,页面加载正常。
  • 我在can't convert undefined的开头和结尾插入了console.log("starting")语句。在加载时查看网络和js控制台输出,createPage()输出发生在网络活动中显示两个API GET请求之前。这是真正发生的事情的代表(即你可以混合javascript控制台和网络控制台时间吗?)

因此,显然我无法在需要时访问数据。

  • 为什么?我的starting不正确吗?
  • 我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

  

Promise.prototype.then()期望2个参数(onFulfilled & onRejected)为function-expression(OR handler or callback),因为它是一个函数(处理程序),当 Promise完成时将调用它

在您的情况下,createPage(first_data, second_data)将在解释器解释语句时调用函数createPage

使用anonymous function作为参数并在其中调用您的函数。

getFirstData()
  .then(getSecondData)
  .then(function() {
    createPage(first_data, second_data);
  });

编辑:如果您没有专门向回调传递任何参数,可以使用.then(FUNCTION_NAME)

答案 1 :(得分:1)

在函数式编程和使用promises中,你应该将getFirstData(和getSecondData)重构为以下形式:

function getFirstData(){
    return new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        var url = "/API/my-request?format=json"
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4 && xhr.status == 200) {
                // Resolve the result, don't assign it elsewhere
                resolve(JSON.parse(xhr.responseText));
            } else {
                // Add rejection state, don't keep the promise waiting
                reject("XHR Error, status = ", xhr.status); 
            }
        }
        xhr.open("GET", url, true);
        xhr.send();
    });
}

然后解决这样的承诺(假设第一个和第二个数据不相互依赖)

Promise.all([getFirstData(), getSecondData()]).then(function(allData){
  var first_data = allData[0];
  var second_data= allData[1];
  return createPage(first_data, second_data);
}).catch(function(error){
  console.log("Error caught: ", error);
});

为了使事情更清晰,您可以从以下位置更改createPages:

function createPage(first_data, second_data){
  // Function body
}

function createPage(data){
  var first_data = data[0];
  var second_data= data[1];
  // Function body
}

和Promise部分:

Promise.all([getFirstData(), getSecondData()]).then(createPage);

注意它变得多么短暂?