返回承诺,但得到“无法读取财产”然后'未定义的'

时间:2016-01-12 16:55:32

标签: javascript promise bluebird

我已经阅读了其他人在此处收到此错误的示例,但在尝试将承诺链接在一起时,我仍然会遇到同样的错误。

在下面的代码中,pegasus(基于promise的http库:https://github.com/typicode/pegasus)调用API,获取一些JSON,并返回一个promise。我可以使用第一个then处理它返回的数据而不会出现问题。这段代码是同步的,最初我没有回复承诺,因为我的印象是它不是必要的(而且可能不是)。在下面的代码中,我尝试将其包装在一个承诺中,因为这是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));
});

知道我可能会出错吗?

2 个答案:

答案 0 :(得分:1)

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

如果我们查看其source code,我们可以看到其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属性,这个函数是没什么奇怪的而不是一个正确的then in Promise感觉到,并返回XHR对象。

正确的then函数会返回一个新的承诺。 pegasus函数及其then都没有返回承诺。

答案 1 :(得分:1)

@Brideau对不起,then可能会让人感到困惑。作为@ T.J。解释说,这不是一个真正的承诺。我将在README中强调这一部分。

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

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

关于“怪异”的代码风格,我正在使用 Byte-saving Techniques。这就是为什么,例如,函数参数被用作变量占位符。

所以Pegasus应该在开始时使用,但之后你可以使用其他库来提出更复杂的请求。

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