Brideau
Brideau

Reputation: 4761

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

I've read through the other examples of people getting this error on here, but I'm continuing to get the same error when trying to chain promises together.

In the code below, pegasus (the promise-based http library: https://github.com/typicode/pegasus) makes a call to an API, gets back some JSON, and returns a promise. I can process the data it returns back using the first then without an issue. This code is synchronous, and initially I wasn't returning a promise because I was under the impression that it wasn't necessary (and still might not be). In the code below I tried wrapping it in a promise anyway as that was a commonly offered solution for other similar questions on Stack Overflow, but that doesn't seem to have solved it either.

Still, I am getting the TypeError: Cannot read property 'then' of undefined message.

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));
});

Any idea where I might be going wrong?

Upvotes: 0

Views: 1284

Answers (2)

Typicode
Typicode

Reputation: 31

@Brideau sorry for that, then may be confusing. As @T.J. explained, it's not a real Promise. I'll emphasise that part in the README.

About not using Promises, the idea of Pegasus is that the faster it loads, the faster it can start making requests.

That's why I'm not using a Promise polyfill. It's to make the library as small as possible. I'm only supporting GET + JSON requests too for the same reason.

Regarding the "weird" code style, I'm using Byte-saving Techniques. That's why, for example, function parameters are used as variable placeholders.

So Pegasus should be used at the begin, but after that you may use other libraries to make more complex requests.

I hope it makes things a bit clearer :)

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074168

The problem is that pegasus doesn't implement A+/Promises. Or, really, any kind of promises in the generally-accepted sense.

If we look at its source code, we can see that its then function doesn't return anything:

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;
}

It's creating an XHR object, then adding a then property to it which is a function which is nothing short of bizarre not a proper then in the Promises sense, and returns that XHR object.

A proper then function returns a new promise. Neither the pegasus function nor its then returns a promise, at all.

Upvotes: 1

Related Questions