Synchronous handling of a method returning a promise.

57 views
Skip to first unread message

Kevin Burton

unread,
Dec 28, 2015, 1:29:19 PM12/28/15
to Q Continuum (JavaScript)
I have a method that returns a promise but when I execute the function in the debugger the promise is neither rejected or resolved. It is basically in the "pending" state. But because of the speed of the machine the debugger stops/quits before the promise can be resolved or rejected. Is there a function that I can call that will not return until the promise is either pending or resolved. the JQuery "always" method. But this method seems to be available only on the client side and I don't see a way of using it with node.

Ideas?

Thank you.


Dylan Mikus

unread,
Dec 28, 2015, 3:15:53 PM12/28/15
to q-con...@googlegroups.com

JQuery .always looks to be equivalent to .then(callback, callback), where you just pass the same callback function twice. Or https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback

If you want to get really hacky, you could have a loop that checks the whether the promise is settled using promise.isPending() and return when it’s pending, but that wouldn’t make any sense for production code. I might be misunderstanding your intentions, but if you have code waiting on the result of the promise-returning method, you should take the result of method and .then it.

So, instead of:

var prom = method();
runAfterPromSettle();

do this:

var prom = method;
prom.then(runAfterPromSettle())
    .catch(handleErrors());

--
You received this message because you are subscribed to the Google Groups "Q Continuum (JavaScript)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to q-continuum...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Dylan Mikus
BS in Computer Science from CMU
dbm...@gmail.com

Kevin Burton

unread,
Dec 28, 2015, 3:25:14 PM12/28/15
to Q Continuum (JavaScript)
I tried

var prom = method; prom.then(runAfterPromSettle()) .catch(handleErrors());

But this doesn't seem to handle the case of a pending promise. What if the promise is neither resolved or rejected? I don't want the function promisesShouldBeHandeled to execute until the promise has either been resolved or rejected.

var prom = method; prom.then(runAfterPromSettle()) .catch(handleErrors());

promiseShouldBehandled();

Dylan Mikus

unread,
Dec 28, 2015, 5:05:15 PM12/28/15
to q-con...@googlegroups.com

If you want promiseShouldBeHandled() to run after the promise resolves or rejects, then your code will be:

var prom = method();
prom.then(promiseShouldBeHandled,
          promiseShouldBeHandled);

If you want three different code paths (promise is resolved, promise is rejected, promise is unsettled), then it would be best to rethink how you are structuring the code, because that doesn’t really align with the way promises should be used. It’s less of a branching control-flow mechanism, and more of a way of treating asynchronous code synchronously. Forgive me if I sound pedantic and that isn’t what you are going for.

If you expect that the promise might never settle, you could have a timeout and reject the promise after a certain amount of time.


--
You received this message because you are subscribed to the Google Groups "Q Continuum (JavaScript)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to q-continuum...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kevin Burton

unread,
Dec 28, 2015, 8:20:07 PM12/28/15
to Q Continuum (JavaScript)
I don't think I have explained it well.

With the code

var prom = method; prom.then(function() {
console.log("Success");
}) .catch(function(err) {
console.log("Failure");
});

console.log("Pending");

The problem is that the output from the above is

Pending

Because the node quits after "Pending" the success or failure paths never even get a chance to run. It is not that the promise never resolves. It is that it never gets the chance to resolve. I need some sort of loop where I have the print out "Pending" so the thread can give up processing to wait for success or failure. I don't want a polling loop but if that is how to best to solve this then so be it.

Thank you.

Dylan Mikus

unread,
Dec 29, 2015, 10:08:08 AM12/29/15
to q-con...@googlegroups.com

Ah, yeah. Sorry for misunderstanding you. I guess if that’s the end of the program, then any non-blocking control-flow wouldn’t hold it up from exiting. Seems like a polling loop or some event loop is necessary.

If you don’t mind me asking, what’s the mechanism/function that’s causing a delay in promise resolution? If I use the following code, Node.js will wait until the timeout fires to exit.

var Q = require('q');

var prom = Q.Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve('success');
    }, 2000);
});

prom.then(function() {
    console.log("Success");
}).catch(function(err) {
    console.log("Failure");
});

console.log('Pending');

I’m curious about what asynchronous functions don’t hold up Node from exiting.


--
You received this message because you are subscribed to the Google Groups "Q Continuum (JavaScript)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to q-continuum...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kevin Burton

unread,
Dec 29, 2015, 11:13:35 AM12/29/15
to Q Continuum (JavaScript)
The method actually actually constructs a JavaScript promise (new Promise) and returns that. Maybe node and Q get along better and the method should be changed to return a Q promise. Here I thought they were all the same. One of the first actions in the method that might hold things up also returns a promise but I don't know what type it is. It is a promise returned by the 'mssql' package (like sql.connect(...).then . . . .).

Kevin Burton

unread,
Dec 29, 2015, 11:25:26 AM12/29/15
to Q Continuum (JavaScript)
I tried returning a Q promise but I get the same result. Without boring you with the details here is what I think the applicable code looks like:

dfi.createNodes = function() {
   
return Q.Promise(function(resolve, reject) {

       
var config = {
           
server: 'db3dev',
           
database: 'EForms',
           
driver: 'msnodesqlv8',
           
options: {
               
trustedConnection: true
            }
       
};

       
sql.connect(config).then(function() {


Wout Mertens

unread,
Dec 30, 2015, 3:43:11 PM12/30/15
to Q Continuum (JavaScript)

Are you sure that you are calling method? You don't seem to…

I'm sure that node doesn't exit as long as there is anything scheduled. You can verify yourself by also calling a setTimeout, node won't exit until that's done.


--
You received this message because you are subscribed to the Google Groups "Q Continuum (JavaScript)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to q-continuum...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--

Wout.
(typed on mobile, excuse terseness)

Kris Kowal

unread,
Jan 2, 2016, 7:32:41 PM1/2/16
to Q Continuum (JavaScript)
There is no function that you can call on a promise that will block until the promise is resolved. This is because such a function does not fit with JavaScript’s "events run to completion" concurrency model. A blocking call would prevent other events from running, and those events are necessary to make progress on a pending promise.

In a language that has "fibers", such a method would typically be called "join". One such existed in an early version of Node.js. Fibers eliminate the guarantee that no other events will be interleaved in your code, which makes it fundamentally more difficult to protect invariants (assumptions). They instead provide the weaker guarantee that no other events will be interleaved, unless you call a function. Threads provide no guarantee at all, so the programmer must explicitly protect concurrency invariants.
Reply all
Reply to author
Forward
0 new messages