mjackson / mach

HTTP for JavaScript
810 stars 41 forks source link

Unexpected mach.get() promise behavior #73

Open nicholascloud opened 9 years ago

nicholascloud commented 9 years ago

I am using mach.get() in conjunction with the Mach HTTP server functionality, and I'm seeing an inconsistency in how return values are propagated through the promise chain.

For example, the following route successfully fetches the Github tag data, but when conn.json() is returned in the success callback it writes nothing to the response stream.

// route example 1
app.get('/mach/tags', function (conn) {
  function addUserAgent(conn) {
    conn.request.setHeader('User-Agent', 'nicholascloud/mach');
  }
  return mach.get('https://api.github.com/repos/mjackson/mach/tags', addUserAgent).then(function (conn) {
    var tags = [];
    JSON.parse(conn.responseText).forEach(function (tagData) {
      tags.push(tagData.name);
    });
    return conn.json(200, tags.sort(semver.rcompare));
  }, function (err) {
    return conn.json(500, {err: err.message});
  });
});
$ curl -v http://localhost:8080/mach/tags
* Hostname was NOT found in DNS cache
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /mach/tags HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sun, 12 Apr 2015 02:42:04 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact

However, if another promise is created by adding another then() to the promise chain, it works fine.

// route example 2
app.get('/mach/tags', function (conn) {
  function addUserAgent(conn) {
    conn.request.setHeader('User-Agent', 'nicholascloud/mach');
  }
  return mach.get('https://api.github.com/repos/mjackson/mach/tags', addUserAgent).then(function (conn) {
    var tags = [];
    JSON.parse(conn.responseText).forEach(function (tagData) {
      tags.push(tagData.name);
    });
    return tags.sort(semver.rcompare);
  }).then(function (tags) {
    return conn.json(200, tags);
  }, function (err) {
    return conn.json(500, {err: err.message});
  });
});
$ curl -v http://localhost:8080/mach/tags
* Hostname was NOT found in DNS cache
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /mach/tags HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Sun, 12 Apr 2015 02:45:53 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
["v1.3.4","v1.3.3","v1.3.2","v1.3.1","v1.3.0","v1.2.0","v1.1.0","v1.0.2","v1.0.1","v1.0.0","v1.0.0-rc4","v1.0.0-rc3","v1.0.0-rc2","v1.0.0-rc1","v0.12.0","v0.11.0","v0.10.1","v0.10.0","v0.9.3","v0.9.1","v0.9.0","v0.8.0","v0.7.0","v0.6.3","v0.6.2","v0.6.1","v0.6.0","v0.5.4","v0.5.3","v0.5.2"]/

I would expect the second route's behavior to be that of the first.