Promise Chain Completion

I come across a Promise warning about an inextricable chain of promises ("a promise was created in the handler, but was not returned from it"). I'm new to Promises, and I suspect I'm using event-based thinking when I shouldn't be. But I'm not sure how to proceed. All this is in the nodejs project.

I am interacting with the ZWave server to turn on and off the light sources. This interaction takes the form of sending HTTP requests to the server that manages the ZWave network. I use Promises due to asynchronous interaction with HTTP.

At one level of my program, I defined the following class method:

ZWave.prototype.onOff = function (nodeNumber, turnOn) { var self = this; var level = turnOn ? 255 : 0; return new Promise(function (resolve, reject) { self.requestAsync(sprintf('/Run/devices[%d].instances[0].commandClasses[0x20].Set(%d)', nodeNumber, level)) .then(function (value) { resolve(value == 'null'); }) .catch(function (error) { reject(error); }); }); 

};

The requestAsync method method is the one that actually interacts with the ZWave server. Conceptually, in onOff (), I try to turn on a specific light identified by this .nodeNumber, either turn it on or off, and then return the result of this query.

onOff () is called from a method of the Switch class that represents a particular light, as follows:

  this.onOff = function( turnOn ) { var state = turnOn ? 'ON' : 'OFF'; var self = this; zWave.onOff( this.nodeNumber, turnOn ) .then( function() { winston.info( sprintf( '%s: turned %s', self.displayName, state ) ); return true; } ) .catch( function( error ) { winston.info( sprintf( '%s: error while turning %s => %s', self.displayName, state, error ) ); return false; } ); } 

The operations "return true" and "return false" are my attempt to end the Promise chain. But it does not work, and I still get a warning.

This puts me as a concrete example of a more general problem: how do you move from a Promise-based model to a traditional blocking code?

Edit

Answering a few questions from the comments ...

I am using bluebird.

zWave.onOff () returns a promise.

Switch.onOff () and zWave.onOff () are different functions in separate classes.

All code is javascript.

Edit 2

I believe that I implemented the jfriend00 suggestions, although I included the .catch () handler in the zWave.onOff () function, but I still get the same unhandled promise error:

 ZWave.prototype.onOff = function (nodeNumber, turnOn) { var self = this; var level = turnOn ? 255 : 0; return self.requestAsync( sprintf( '/Run/devices[%d].instances[0].commandClasses[0x20].Set(%d)', nodeNumber, level ) ) .then( function( value ) { resolve( value == 'null' ); } ) .catch( function( error ) { reject( error ); } ); }; 

and

 // function inside Switch class this.onOff = function( turnOn ) { var state = turnOn ? 'ON' : 'OFF'; var self = this; return zWave.onOff( this.nodeNumber, turnOn ).reflect() .then( function() { winston.info( sprintf( '%s: turned %s', self.displayName, state ) ); return true; } ) .catch( function( error ) { winston.info( sprintf( '%s: error while turning %s => %s', self.displayName, state, error ) ); return false; } ); } 

Here is the warning text:

Warning: a promise was created in the handler, but was not returned from it on ZWave.requestAsync (/home/mark/XmasLights/zWaveRequest.js:19:12) in ZWave.onOff (/home/mark/XmasLights/zWaveRequest.js: 93:17) at onOff (/home/mark/XmasLights/switch.js:42:22) at updateCron (/home/mark/XmasLights/switch.js:80:18) at dailyUpdate (/ home / mark / XmasLights / app.js: 196: 21) in /home/mark/XmasLights/app.js:134:58 on processImmediate [like _immediateCallback] (timers.js: 383: 17)

Sorry to run when formatting the warning, I cannot get stackoverflow to correctly separate lines.

+7
javascript promise
source share
1 answer

According to Bluebird docs, this warning occurs when you create a promise in the promise area, but you do not return anything from this Promise area. Bluebird discovers that you are creating a promise within the promise handler, but did not return anything from this handler, which is potentially an unrelated promise when it should be associated with other promises. You can read what they say about the problem here .

In the open code, you are not showing anything similar to the Bluebird examples in your document, but I would suggest that one problem is here:

 ZWave.prototype.onOff = function (nodeNumber, turnOn) { var self = this; var level = turnOn ? 255 : 0; return new Promise(function (resolve, reject) { self.requestAsync(sprintf('/Run/devices[%d].instances[0].commandClasses[0x20].Set(%d)', nodeNumber, level)).then(function (value) { resolve(value == 'null'); }).catch(function (error) { reject(error); }); }); }; 

Where you better avoid the anti-pattern and do this:

 ZWave.prototype.onOff = function (nodeNumber, turnOn) { var level = turnOn ? 255 : 0; return this.requestAsync(sprintf('/Run/devices[%d].instances[0].commandClasses[0x20].Set(%d)', nodeNumber, level)).then(function (value) { return(value == 'null'); }); }; 

There is no need to create a new promise, because you already have one that you can simply return. You can learn more about the type of anti-pattern exception that you used here .


And another possible problem here is when you create a return promise value but not return it from the this.onOff method. You explicitly made return true; or return false; from your .then() handlers, but then you never do anything with this return value, because there are no subsequent .then() handlers, and the promise itself is not returned.

 this.onOff = function( turnOn ) { var state = turnOn ? 'ON' : 'OFF'; var self = this; zWave.onOff( this.nodeNumber, turnOn ) .then( function() { winston.info( sprintf( '%s: turned %s', self.displayName, state ) ); return true; } ) .catch( function( error ) { winston.info( sprintf( '%s: error while turning %s => %s', self.displayName, state, error ) ); return false; } ); } 

I would suggest changing this to return the promise as follows:

 this.onOff = function( turnOn ) { var state = turnOn ? 'ON' : 'OFF'; var self = this; // ===== add return statement here return zWave.onOff( this.nodeNumber, turnOn ) .then( function() { winston.info( sprintf( '%s: turned %s', self.displayName, state ) ); return true; } ) .catch( function( error ) { winston.info( sprintf( '%s: error while turning %s => %s', self.displayName, state, error ) ); return false; } ); } 

This then provides a true or false return promise to the caller .onOff() . Or, if you do not need to get these return values, you can remove the return true and return false so that there are no promises.

This puts me as a concrete example of a more general problem: how do you move from a Promise-based model to a traditional blocking code?

You do not write traditional locking code for asynchronous operations. Asynchronous operations are asynchronous and will never be traditional blocking code. Promises provide much more structure for managing and coordinating asynchronous operations, but you still have to write code for them in asynchronous mode. Just write this asynchronous code using promises.

JS adds more features, such as generators, and expects what you can use for this. Here is a short article on this topic: ESIN async functions .

+6
source share

All Articles