Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

return thunk for generators #230

Closed
tj opened this issue Jun 6, 2013 · 23 comments
Closed

return thunk for generators #230

tj opened this issue Jun 6, 2013 · 23 comments

Comments

@tj
Copy link
Contributor

tj commented Jun 6, 2013

so we can do:

  var res = yield request
    .get('http://google.com')
    .set('Accept', 'application/json')
    .query({ search: 'sloths' })
    .end();

  console.log(res.status);
@jkroso
Copy link

jkroso commented Jun 6, 2013

not that it makes much difference when using them with generators but it might be worth a look at making the request instances also promise instances.

  var res = yield request
    .get('http://google.com')
    .set('Accept', 'application/json')
    .query({ search: 'sloths' })

  console.log(res.status);

promises are just a little nicer for other abstractions which are usable now. whatever though thunks do the job in any case.

@shesek
Copy link
Contributor

shesek commented Jun 6, 2013

Looks like its for superagent to work with co? (which looks awesome, @visionmedia!).

If co were to support promises (which is basically just [1] replacing ret.value(next) with (ret.value.then||ret.value)(next)) its just a matter of aliasing the end method with then... but it looks like co is pretty opinionated about not using promises.

Edit: [1] actually, its not quite right - promises don't follow the (err, res) callback convention and use two callbacks instead. It would also be wrong to alias end as then for that reason.

@tj
Copy link
Contributor Author

tj commented Jun 6, 2013

yeah I'm not a fan of promises, not going to go that route, this is a nice one line change

@tj
Copy link
Contributor Author

tj commented Jun 6, 2013

plus .query() doesn't actually initiate the request so that would be sketchy

@jkroso
Copy link

jkroso commented Jun 6, 2013

no the generator thing would call then and that would start the request (or pipe, lol, if it preferred). if you like to minimize implicit stuff you can add .then() with no args after .query and nothing changes. I would love to hear a proper explanation of why you dislike promises, but fair enough if you just wan't to get on with it ;)

@tj
Copy link
Contributor Author

tj commented Jun 7, 2013

I just don't really like that amount of "cruft" as a base, especially when a perfectly good alternative is to just return a function: https://github.com/visionmedia/co-exec/blob/master/index.js#L12

no fighting over which implementation to use or duplicate implementations etc. Even if there was one particular method to use I dont think .then() is a great one personally but it is what it is!

@jkroso
Copy link

jkroso commented Jun 7, 2013

no fighting over which implementation to use or duplicate implementations etc

good point people still disagree a lot on how to implement them.

I really wish this was the standard https://gist.github.com/jkroso/5689012#file-promise-js but instead most people use stuff like q which makes me cringe :(. I guess without agreement on what a promise should be thunks are a pretty good alternative

@tj
Copy link
Contributor Author

tj commented Jun 7, 2013

yeah seems like too much boilerplate for something effectively every library would require, at least with thunks there's only one way you can do it haha

@spikebrehm
Copy link

Curious if @visionmedia has any renewed interest in supporting promises now that it's a sure thing for ES6?

@tj
Copy link
Contributor Author

tj commented Dec 23, 2013

not really, impartial once they're actually implemented in browsers, but IMO it's a really silly thing to add to the language, easier to just return a function

@jkroso
Copy link

jkroso commented Dec 24, 2013

superagent requests pretty much already are promises so I think they may aswell become yieldable ones. The new ES6 promises won't help though since they aren't sub-classable :(.

BTW: I rewrote superagent to use promises and here is an example of which demonstrates why some people go for promises over thunks. Promises are more a type than mechanism. If you could distinguish thunks from other functions cleanly then I'd prefer them too.

@jonathanong
Copy link

can we get this in? are there any blockers?

@gjohnson
Copy link
Contributor

@gjohnson
Copy link
Contributor

@jonathanong started messing with this, it's my first go around with generators so still figuring out some things. Feel free to fix this branch: https://github.com/visionmedia/superagent/tree/thunkify

@hallas
Copy link
Contributor

hallas commented Mar 19, 2014

@gjohnson lets add some tests for the thunk branch

@arcmode
Copy link

arcmode commented Aug 8, 2014

I use this

var co = require('co');
var request = require('superagent');

co(function *(){
  var a = yield request.get('http://google.com').thunkify();
  var b = yield request.get('http://yahoo.com').thunkify();
  var c = yield request.get('http://cloudup.com').thunkify();
  console.log(a.statusCode);
  console.log(b.statusCode);
  console.log(c.statusCode);
})()

co(function *(){
  var a = request.get('http://google.com').thunkify();
  var b = request.get('http://yahoo.com').thunkify();
  var c = request.get('http://cloudup.com').thunkify();
  var res = yield [a, b, c];
  console.log(res);
})()

@ianstormtaylor
Copy link

+1 for thunks

@matthewmueller
Copy link
Contributor

+1 for @visionmedia's original API. Not a huge fan of .thunkify(), you can just do:

var thunkify = require('node-thunkify');
request.get = thunkify(request.get);
yield request.get('http://google.com')

If you need it on the shorthand.

@kof
Copy link
Contributor

kof commented Sep 25, 2014

  1. Promises have a way bigger value proposition than thunks.
  2. Performance overhead can be ignored in superagent use case.
  3. We don't need to introduce a dependency to some particular implementation. We can let user pass the implementation once or use the global one.
  4. We can still have the .end method which returns a promise, which is more explicit and backwards compatible.

@cncolder
Copy link

i have a new idea:

we can extend the prototype of superagent.Request as thenable.

Request.prototype.then = function(fulfilled, rejected) {
  return new Promise(function(resolve, reject) {
    this.end(function(err, res) {
      if (err) reject(err);
      else resolve(res);
    });
  }.bind(this)).then(fulfilled, rejected);
};

now we can get promise after then or yield.

request.get('localhost:3000')
.then(function(res) {
  assert(res.ok);
  return res;
})
.then(function(res) {
  assert.equal(res.text, 'Hello World');
});

co(function * () {
  var res = yield request.get('localhost:3000');
  assert(res.ok);
})();

@defunctzombie
Copy link
Contributor

Dislike promises. Right now they are not widely supported enough and I don't see a reason to use them for this since a request is a one shot deal.

@nmn
Copy link
Contributor

nmn commented Nov 29, 2014

This has been a long and unproductive argument, which is mostly a thunks vs promises debate.

Some things to consider now:

  1. Co now prefers promises over thunks
  2. superagent-promise already provides a simple wrapper for superagent to return promises
  3. Choosing one does not mean the other is bad.

Possible resolutions:

  1. support thunks in the main lib, and support the development of superagent-promise to support both approaches.
  2. Leave the main lib alone, and create a separate repo to wrap superagent and make it support thunks, and support superagent-promise
  3. Add Support for both thunks and promises into the main lib, possibly with an extra method (toThunk/toPromise?)
  4. Choose one approach as the only approach and keep arguing about it for eternity

@defunctzombie
Copy link
Contributor

I don't care for thunks or promises right now in this lib. This is a one shot callback lib. Once people rally around the way async will be done going forward, then might revisit. My comment is not meant to be about one being better than the other, only about having more dependencies for this lib right now for no reason. Functions are simple and easy to understand.

@ladjs ladjs locked and limited conversation to collaborators Nov 29, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.