Clean shallow chains

This is easy if these are all my functions, but I can also do this with third party libraries via denodeify (a feature of the promise.js library, though most promise libraries have something similar) – turn a callback pattern function into a promise based function:

Though one place I've been caught out with denodeify is when the method relies on method's context, which is most things as it turns out (fs is just a fluke that it's methods don't rely on the context), so make sure to bind as required:

Prebaking

You've already seen that I use bind, but I've also found that in some situations, I need to call a function with static arguments (i.e. not relying on the previous promise), just because it's part of the promise chain.

This also allows me to code with the shallow chains as above, because it (to me) feels a bit verbose to drop into a function just to return a promise straight back out that doesn't depend on any unknown variable.

The thing to watch out for is if the function behaves differently if there's more arguments, I have to cold call the promise.

Cold calling

Disclaimer:this patterned is required due to my own prebaking patterns and attempts to (ironically) simplify. There's a good chance you won't need this!

When a function works both as a promise and using the callback pattern - it's great, but I've been caught out in the past.

The way the function might work under the hood is something like (this pseudo code):

Heroku.prototype.post=function(slug, options, callback){// do some async thingthis.request(slug, options,function(error, data){// ** this line is how the dual functionality works ** //if(callback)callback(error, data);// else do something with promise});// return some promise created some placereturnthis.promise;}

The issue is when domain is called, it's actually called with the prebaked arguments of the slug and options but also the resolved value from create() - so a third argument is received.

This third argument is the resolved result of create() which is treated as the callback argument and as a function object, so the code will try to invoke it - causing an exception.

My solution is to wrap in a cold call - i.e. a newly created function that calls my method with no arguments. Like bind once but then never allow any new arguments, also known as currying (here's a simple demo of the curry/partial/seal type-thing):

This may well be so, but there's a few key benefits to my code when I throw:

I'm used to error first handling, and quite often I'll accidently recieve reject as the first argument, which leads to much confusion. This way, I only ever accept resolve as my argument. There's also issues where "reject" and "resolve" as words are visually similar, which has also lead to confusion when they're the wrong way around!

I don't have to remember to return reject. I've seen code that doesn't return on reject, and it then goes on to resolve with a value. Some libraries fulfill, some reject, some throw new errors. Throwing the error avoids this entirely.

This is also consistent with the way I'll deal with errors inside of subsequent then calls:

Links

Remy Sharp

I'm a JavaScript developer working professionally on the web since 1999. I run my own consultancy, build products, run training, speak at conferences and curate the UK's best JavaScript conference. You can hire me too.