17

I'm currently experimenting with promises and have a really basic question!

Within a promise chain, would it be bad practice to call a synchronous function? For example:

.then(function(results) {

    if(checkIfResultInMemory(results) === true){
       return getTotalFromMemory()
    }

   return results;

  })

Or should my sync functions be refactored to return promises also?

Ben
  • 6,026
  • 11
  • 51
  • 72

2 Answers2

33

Within a promise chain, would it be bad practice to call a synchronous function?

No, it is not a bad practice at all. It is one of many expected and useful practices.

You are perfectly free to call either synchronous functions within the promise chain (from within .then() handlers) or asynchronous functions that then return a new promise.

When you return something from a .then() handler, you can return either a value (which becomes the resolved value of the parent promise) or you can return another promise (which chains onto the previous promise) or you can throw which works like returning a rejected promise (the promise chain becomes rejected).

So, that means you can call a synchronous function and get a value from it or call an async function and get another promise and then return either from the .then() handler.

All of these synchronous things are perfectly legal and each have their own objective. Here are some synchronous happenings in the .then() handler:

// modify resolved value
someAsync().then(function(val) {
    return val + 12;
});

// modify resolved value by calling some synchronous function to process it
someAsync().then(function(val) {
    return someSynchronousFunction(val);
});

// synchronously check the value and throw to change the promise chain
// to rejected
someAsync().then(function(val) {
    if (val < 0) {
        throw new Error("value can't be less than zero");
    }
    return val;
});

// synchronously check the value and return a rejected promise 
// to change the promise chain to rejected
someAsync().then(function(val) {
    if (val < 0) {
        return Promise.reject("value can't be less than zero");
    }
    return val;
});

Here's a little example of an async operation that returns a promise followed by three synchronous .then() handlers and then outputting the final value:

function delay(t, val) {
    return new Promise(function(resolve) {
        setTimeout(function() {
            resolve(val);
        }, t);
    });
}

function increment5(val) {
    return val + 5;
}

delay(500, 10).then(increment5).then(function(val) {
    return val - 3;
}).then(function(final) {
    document.write(final);
});

Note: You only generally only want to use promises when you have or may have asynchronous operations because if everything is synchronous, then pure synchronous code is both faster to execute and easier to write. But, if you already have at least one async operation, you can certainly mix synchronous operations with that async operation and use promises to help structure the code.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Many thanks @jfriend00 - very helpful indeed! Thanks for your time. – Ben Dec 18 '15 at 04:15
  • 1
    Why the downvote? Downvotes of a generally accepted answer without any accompanying comment that explains why you think it deserved a downvote don't really contribute much to the community. If you explain, then the author can improve their answer to address your issue and improve the answer for all. Driveby downvoting doesn't help improve things for the rest of the community. – jfriend00 Mar 31 '17 at 19:31
  • Excellent answer. Much better than the mythical "never do synchronous promises". Thanks. – Kim Nov 12 '17 at 06:39
  • @Kim - Thanks, but just to be absolutely clear here, these aren't "synchronous promises". All `.then()` handlers are always called asynchronously, even if the underlying operation is synchronous. And, I think it goes without saying that one would only use promises if there was at least one asynchronous operation involved. Otherwise, promises just complicate things for purely synchronous code. But, it is perfectly OK to call some synchronous code from within your promise chain. – jfriend00 Nov 12 '17 at 07:34
  • @jfriend00 I think I was being a bit lazy calling them that. I do understand, thanks. – Kim Nov 13 '17 at 16:43
2

A then callback function should:

  • return another promise
  • return a synchronous value (or undefined)
  • throw a synchronous error
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
trquoccuong
  • 2,857
  • 2
  • 20
  • 26