I am running into a Promise warning about an unterminated Promise chain ('a promise was created in a handler but was not returned from it'). I am new to Promises, and suspect I'm using non-event-driven thinking when I shouldn't be. But I'm not sure how to proceed. This is all within a nodejs project.
I am interacting with a ZWave server to turn lights on and off. That interaction takes the form of making http requests to a server which controls the ZWave network. I'm using Promises because of the asynchronous nature of interacting via http.
At one level of my program I have the following class method defined:
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 class method is the one that actually handles interaction with the ZWave server. Conceptually, in onOff() I'm trying to turn a particular light, identified by this.nodeNumber, either on or off, and then return the result of that request.
onOff() is being called from a Switch class method, representing 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 'return true' and 'return false' statements are my attempt to end the Promise chain. But it's not working, and I'm still getting the warning.
This strikes me as a specific example of a more general issue: how do you move from a Promise-based model to traditional blocking code?
Edit
Answering a few questions from comments...
I'm using bluebird.
zWave.onOff() returns a promise.
Switch.onOff() and zWave.onOff() are distinct functions in separate classes.
All the code is javascript.
Edit 2
I believe I have implemented jfriend00's suggestions, although I included a .catch() handler in the zWave.onOff() function, but I am still getting 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 text of the warning:
Warning: a promise was created in a handler but was not returned from it at ZWave.requestAsync (/home/mark/XmasLights/zWaveRequest.js:19:12) at 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) at /home/mark/XmasLights/app.js:134:58 at processImmediate [as _immediateCallback] (timers.js:383:17)
Sorry about the run on formatting of the warning, I can't seem to get stackoverflow to separate the lines properly.