33

I'm studying the promises pattern and using kriskowal's q for node.js,

having this snippet:

var deferred = Q.defer();
try {
    messageData = JSON.parse(message);
} catch (e) {
    global.logger.warn('Error parsing JSON message.');
    deferred.reject(e);
}
...
if (some_reason)
    deferred.resolve(something);
...
return deferred.promise;

What if both the parser fails and some_reason is true?

Will the execution procede from rejecting through resolving and both promise's method be called at different times, thus generating a bug?

Should i avoid to call reject/resolve multiple times?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Luca Vitucci
  • 3,674
  • 4
  • 36
  • 60

2 Answers2

53

Since promises can only resolve once (to either fulfilled or rejected), the first resolution wins and any further calls will be ignored. From the docs:

In all cases where a promise is resolved (i.e. either fulfilled or rejected), the resolution is permanent and cannot be reset. Attempting to call resolve, reject, or notify if promise is already resolved will be a no-op.

Should i avoid to call reject/resolve multiple times?

You can even design your application letting two methods "race" against each other to resolve a deferred, but in general it should be avoided to reduce confusion of a reader.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I don't know about the race, I've used jQuery deferreds exactly for that. e.g. go to the next screen once the user clicks or when the time runs out. "Whichever comes first". I find it strange that libraries like Kew.js actually throw an error when trying to resolve twice. :( – fregante Jun 09 '14 at 17:30
  • @bfred.it: Yes, you *can* do that. But it's better to explicitly do `Q.race(getNextUserClick(), Q.timeout(…)).then(nextScreen)` than [having a single deferred](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#the-deferred-anti-pattern) and manually resolving that multiple times. – Bergi Jun 09 '14 at 17:40
  • `Race` is interesting but kew.js doesn't actually have that, unfortunately. – fregante Jun 09 '14 at 20:49
  • https://jsbin.com/gemepay/3/edit?js,console ; By this example, since the first promise resolves into a value of 1, afterwards why do the other calls resolve to 1 also ? By this I understand that once resolved, the other '.then()' calls default to the value that was first computed. – motan Sep 13 '19 at 13:10
  • 1
    @motan It's unclear what you mean by "*the first promise*". There is only a single promise (of relevance) in your code, `p`, and that single promise does have a single result value. It doesn't matter how many `then` callbacks are installed on a promise - zero, one, or many - they don't affect the resolution of the promise. – Bergi Sep 13 '19 at 13:52
0

original post here

see github gist: reuse_promise.js

/*
reuse a promise for multiple resolve()s since promises only resolve once and then never again
*/

import React, { useEffect, useState } from 'react'

export default () => {
    
    const [somePromise, setSomePromise] = useState(promiseCreator())
        
    useEffect(() => {
        
        somePromise.then(data => {
            
            // do things here
            
            setSomePromise(promiseCreator())
        })
        
    }, [somePromise])
}

const promiseCreator = () => {
    return new Promise((resolve, reject) => {
        // do things
        resolve(/*data*/)
    })
}
ddaaggeett
  • 149
  • 2
  • 10