Javascript 链式承诺会给出未定义的函数错误,但我可以单独执行这些函数

Javascript 链式承诺会给出未定义的函数错误,但我可以单独执行这些函数,javascript,promise,Javascript,Promise,在我的网页中设置一些span的textContent之前,我正在尝试链接一些API调用。我可以通过将以下ajax API调用粘贴到控制台中来分别执行它们,但是当我将它们作为承诺链接时,我得到的getFirstData()是未定义的 var first_data = [], second_data = []; function getFirstData(){ var xhr = new XMLHttpRequest(); var url = "/API/first-dat

在我的网页中设置一些
span
textContent
之前,我正在尝试链接一些API调用。我可以通过将以下ajax API调用粘贴到控制台中来分别执行它们,但是当我将它们作为承诺链接时,我得到的
getFirstData()是未定义的

var first_data = [],
    second_data = [];

function getFirstData(){
    var xhr = new XMLHttpRequest();
    var url = "/API/first-data?format=json"
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            first_data = JSON.parse(xhr.responseText);
            return Promise.resolve('1');
        }
    }
    xhr.open("GET", url, true);
    xhr.send();
}

/*getSecondData is the same, but with a different API url. I'll DRY these 
two into one function that takes a url argument when I get it working.*/

getFirstData().then(getSecondData).then(createPage);
这是在
标签之间,就在
之前。那么,最后一行调用
getFirstData()
导致解释器说它是
未定义的
有什么问题呢?作为参考,在网络日志中,会发送getSecondData(),并返回很好的结果


(注意:我特别尝试在没有JQuery的情况下执行此操作)。

getFirstData
没有返回承诺,它返回的是
未定义的
,这是不可执行的

function getFirstData(){
    return new Promise(function(resolve) {
      var xhr = new XMLHttpRequest();
      var url = "/API/first-data?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();
    });
}

getFirstData
没有返回它返回的
未定义的
承诺,该承诺不可返回

function getFirstData(){
    return new Promise(function(resolve) {
      var xhr = new XMLHttpRequest();
      var url = "/API/first-data?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();
    });
}

出现此问题的原因是,您的函数在有机会返回
Promise.resolve('1')
之前返回
未定义的
(换句话说,在返回之前到达函数块的末尾)

您的函数必须立即返回一个Promise对象,该对象在最终在AJAX处理程序内解析之前变为挂起

我还将使用提供的
reject
参数添加错误处理,这是Promise对象的标准

function getFirstData(){
    return new Promise(function(resolve, reject) { // encapsulate code in a promise which returns immediately
      var xhr = new XMLHttpRequest();
      var url = "/echo/json"
      xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && xhr.status == 200) {
              first_data = JSON.parse(xhr.responseText);
              return resolve('1');
          }
          else {
            return reject('There was an error!') // reject the promise if error occurs
          } 
      }
      xhr.open("GET", url, true);
      xhr.send();
    });
}
然后用绳子把它拴起来:

getFirstData()
.then(getSecondData)
.catch(function(err){Throw err}) // catch the error if it throws
.then(createPage);

请参见“工作”

发生此问题的原因是,在函数有机会返回
Promise.resolve('1')
之前,函数正在返回
未定义的
(换句话说,在返回之前到达函数块的末尾)

您的函数必须立即返回一个Promise对象,该对象在最终在AJAX处理程序内解析之前变为挂起

我还将使用提供的
reject
参数添加错误处理,这是Promise对象的标准

function getFirstData(){
    return new Promise(function(resolve, reject) { // encapsulate code in a promise which returns immediately
      var xhr = new XMLHttpRequest();
      var url = "/echo/json"
      xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && xhr.status == 200) {
              first_data = JSON.parse(xhr.responseText);
              return resolve('1');
          }
          else {
            return reject('There was an error!') // reject the promise if error occurs
          } 
      }
      xhr.open("GET", url, true);
      xhr.send();
    });
}
然后用绳子把它拴起来:

getFirstData()
.then(getSecondData)
.catch(function(err){Throw err}) // catch the error if it throws
.then(createPage);

请参见工作

您能制作一个可复制的测试用例吗?我可以在我的浏览器上运行并查看问题所在。好的,给我几分钟时间创建一个小提琴。API不是公共的,所以我必须找到其他东西。@Escher JSFIDLE提供测试ajax端点。不,不需要arg。这就是问题所在吗?不是。至少,不是你观察到的问题。你能做一个可复制的测试用例吗?我可以在我的浏览器上运行并查看问题所在。好的,给我几分钟时间创建一个小提琴。API不是公共的,所以我必须找到其他东西。@Escher JSFIDLE提供测试ajax端点。不,不需要arg。这就是问题所在吗?不是。至少,这不是您所观察到的问题。值得注意的是,此函数不处理错误。尽管如此,我还是把它作为OP的练习。值得注意的是,这个函数不处理错误。尽管如此,我还是把它留给OP做练习。