返回承诺,但得到'无法读取属性'那么'的未定义'

Returning a Promise, but getting 'Cannot read property 'then' of undefined'

本文关键字:属性 读取 那么 未定义 返回 承诺      更新时间:2023-09-26

我已经阅读了其他关于人们在这里遇到这个错误的例子,但在尝试将承诺链接在一起时,我仍然会遇到同样的错误。

在下面的代码中,pegasus(基于promise的http库:https://github.com/typicode/pegasus)调用API,返回一些JSON,并返回一个promise。我可以使用第一个then毫无问题地处理它返回的数据。这段代码是同步的,最初我没有返回承诺,因为我觉得它没有必要(现在可能仍然没有)。在下面的代码中,我尝试用promise来包装它,因为这是Stack Overflow上其他类似问题的常见解决方案,但这似乎也没有解决它。

尽管如此,我还是收到了TypeError: Cannot read property 'then' of undefined消息。

var polygonGeo, centroidGeo;
var hexData = pegasus(hexUrl)
  .then(function(data, xhr) {
    return new Promise(function(resolve, reject) {
      var features = data.features;
      var polygons = features.filter(function(feature) {
        return feature.properties.kind === 'Hexagon';
      });
      var centroids = features.filter(function(feature) {
        return feature.properties.kind === 'Centroid';
      });
      polygonGeo = $.extend(true, {}, data);
      centroidGeo = $.extend(true, {}, data);
      polygonGeo.features = polygons;
      centroidGeo.features = centroids;
      if (typeof polygonGeo !== 'undefined' &&
          typeof centroidGeo !== 'undefined') {
        resolve();
      }
    });
}).then(function() {
  console.log('It never reaches here.');
}).catch(function(error) {
  console.log(Error(error));
});

知道我哪里可能出错了吗?

问题是pegasus没有实现A+/Promises。或者,实际上,任何一种普遍接受的承诺。

如果我们查看它的源代码,我们可以看到它的then函数没有返回任何内容:

function pegasus(a, xhr) {
  xhr = new XMLHttpRequest();
  // ...lines omitted...
  xhr.onreadystatechange = xhr.then = function(onSuccess, onError, cb, data) {
      // ...lines omitted, there is no `return` anywhere, at all...
  };
  // Send
  xhr.send();
  // Return request
  return xhr;
}

它创建了一个XHR对象,然后向其添加一个then属性,该属性是一个函数,非常奇怪不是Promises意义上的正确then,并返回该XHR对象。

一个合适的then函数返回一个新的promise。pegasus函数和它的then都不返回promise。

@Brideau很抱歉,then可能会让人困惑。正如@T.J.所解释的,这不是一个真正的承诺。我将在README中强调这一部分。

关于不使用Promises,Pegasus的想法是,它加载得越快,就越快开始发出请求。

这就是为什么我不使用Promise polyfill。这是为了使图书馆尽可能小。出于同样的原因,我也只支持GET+JSON请求。

关于"怪异"的代码样式,我使用字节保存技术。这就是为什么,例如,函数参数被用作变量占位符。

因此,一开始应该使用Pegasus,但之后您可以使用其他库来进行更复杂的请求。

我希望它能让事情变得更清楚:)