简体   繁体   中英

Nodejs promise not working when using q library

I am trying to learn promises on my own. This is the code I wrote -

var Q = require('q');

var promise = Q.fcall(function() {
  // I expect this time out to delay returning the response 7.
  setTimeout( console.log('hi'), 1000 );
  return 7;
});

promise.then(function(contents) {
  console.log(contents);
});
// Added this timeout so that the javascript execution context(node ex.js) remains alive before the code in the then block is resolved.
setTimeout( function(){console.log('bye');}, 1000 );

Now this is not printing the contents. I just get C:\\node\\Ex_Files_UaR_Node\\first>node example3.js hi bye

I was expecting to get - hi 7 bye

Please let me know if there is anything very much evident which I am missing.

EDIT:

PS The below code resolves the promise -

var Q = require('q');

var promise = Q.fcall(function() {
  setTimeout( function(){console.log('hi');}, 1000 );
  return 7;
});

promise.then(function(contents) {
  console.log(contents);
});

setTimeout( function(){console.log('bye');}, 1000 );

However the basic idea behind adding setTimeOut in Q.fcall was to delay the execution of the promise. Any idea how to do that ?

There you go

let p = new Promise((resolve, reject) => {  
   setTimeout(() => resolve(4), 2000);
});

p.then((res) => {  
  console.log(res);
});

ES6 Promises are simpler. p is resolved only after 2 seconds. Till then, It is not resolved, neither rejected. So then executes only after 2 seconds

There is a problem with your 1st log statement.

I've modified your code to work properly.

var Q=require('q');
var promise = Q.fcall(function() {
    setTimeout( function(){console.log('hi')}, 1000 );
    return 7;
})
promise.then(function(contents) {
    console.log(contents);
});

setTimeout(function(){console.log('bye');}, 1000 );

But this code will print 7 , bye and hi in respective order because, the following actions happens syncronously:

  • Promise gets registered with the call to the function fcall() .
  • The promise variable registers a handler using then() method.
  • Your timeout function, which is aiming at logging 'bye', is registered.

Now the following things happens asynchronously in the following order:

  • Your registered promise callback, where you are registering a timeout function to print 'hi' and returning value 7, is called as callback from fcall() .
  • Now the setTimeout registers the function aiming to log 'hi' and returns value 7.
  • Promise gets resolved with value 7 and it logs the value to console.
  • The timeout for 'bye' gets expired and logs it to the console.
  • The timeout for 'hi' gets expired and logs it to the console.

Hope it makes the flow clear.

I could not reproduce the problem of not getting the 7 in the output (even though your code has several logical mistakes), as this snippet (without any of the corrections) does produce it:

 // This is browser version, so `require` is replaced by `script src` tag. //var Q = require('q'); var promise = Q.fcall(function() { // I expect this time out to delay returning the response 7. setTimeout( console.log('hi'), 1000 ); return 7; }); promise.then(function(contents) { console.log(contents); }); // Added this timeout so that the javascript execution context(node ex.js) remains alive before the code in the then block is resolved. setTimeout( function(){console.log('bye');}, 1000 ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/q.js/1.5.0/q.js"></script> 

There are however several issues:

  • The first argument to the first setTimeout is not a function: you pass it console.log('hi') instead of function(){console.log('hi');} .
  • return 7 will be executed immediately. If you want a delay for the initial promise to settle, then Q.fcall is not the method you need: you need Q.Promise instead.

Here is how your intended behaviour would be coded then:

 var promise = Q.Promise(function (resolve, reject) { setTimeout( function () { console.log('hi'); resolve(7); }, 1000 ); }); promise.then(function(contents) { console.log(contents); }); setTimeout( function(){console.log('bye');}, 1000 ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/q.js/1.5.0/q.js"></script> 

Note that Node has a native Promise library with which you can do the same. There is really no need to include Q. Just replace Q.Promise(...) with new Promise(...) :

 var promise = new Promise(function (resolve, reject) { setTimeout( function () { console.log('hi'); resolve(7); }, 1000 ); }); promise.then(function(contents) { console.log(contents); }); setTimeout( function(){console.log('bye');}, 1000 ); 

Note that there is a slight difference in the output order for the "7". This is because the native implementation of Promises uses a microtask to schedule the execution of the then callback, while Q uses an event on the main queue to schedule that execution, which comes later. Many will consider the native behaviour "more correct".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM