结束一个承诺链

我遇到了一个关于一个未终止的Promise链的承诺警告('一个承诺是在一个处理程序中创build的,但没有从它返回')。 我对Promises很陌生,怀疑我不应该使用非事件驱动的思维。 但我不知道如何进行。 这全部在一个nodejs项目中。

我正在与ZWave服务器进行交互以打开和closures灯光。 这种交互采取向控制ZWavenetworking的服务器发出http请求的forms。 我使用Promise是因为通过http进行交互的asynchronous特性。

在我的程序的一个层次上,我定义了下面的类方法:

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); }); }); 

};

requestAsync类方法是实际处理与ZWave服务器交互的方法。 从概念上讲,在onOff()我试图打开一个特定的光,确定this.nodeNumber,或者打开或closures,然后返回该请求的结果。

onOff()被从一个Switch类的方法中调用,代表一个特定的灯光,如下所示:

  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; } ); } 

“返回真实”和“返回虚假”的声明是我试图结束“承诺”链。 但是它不工作,我仍然收到警告。

这让我想起了一个更普遍问题的具体例子:如何从基于Promise的模型转换到传统的阻止代码?

编辑

回答评论中的几个问题

我正在使用蓝鸟。

zWave.onOff()返回一个承诺。

Switch.onOff()和zWave.onOff()在不同的类中是不同的函数。

所有的代码是JavaScript。

编辑2

我相信我已经实现了jfriend00的build议,尽pipe我在zWave.onOff()函数中包含了一个.catch()处理函数,但是我仍然得到了相同的未处理的promise错误:

 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 ); } ); }; 

 // 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; } ); } 

以下是警告的文字:

警告:承诺是在处理程序中创build的,但未在ZWave.requestAsync(/home/mark/XmasLights/zWaveRequest.js:19:12)ZWave.onOff处返回(/home/mark/XmasLights/zWaveRequest.js (/ home / mark / XmasLights):updateCron(/home/mark/XmasLights/switch.js:80:18)onOff(/home/mark/XmasLights/switch.js:42:22) /app.js:196:21)at /home/mark/XmasLights/app.js:134:58 at processImmediate [as _immediateCallback](timers.js:383:17)

对不起,关于警告的格式化运行,我似乎无法得到stackoverflow正确分隔线。

根据蓝鸟文档,当您在承诺范围内创build承诺时会发生此警告,但您不会从该承诺范围中返回任何内容。 Bluebird检测到你在一个promise处理程序中创build了一个promise,但是并没有从这个处理程序返回任何可能是未链接的promise的东西,当它应该被链接到其他的promise时。 你可以在这里阅读他们对这个问题的看法。

在你透露的代码中,你不会展示Bluebird在他们的文档中显示的例子,但是我猜想这里有一个问题:

 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); }); }); }; 

在哪里你最好避免反模式,并做到这一点:

 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'); }); }; 

没有必要在这里创造一个新的承诺,因为你已经有了一个可以返回的承诺。 您可以阅读更多有关避免您在此处使用的反模式types的信息 。


而另一个可能的问题就是在这里创build一个返回承诺值,但是不要从this.onOff方法this.onOff 。 你已经明确地做了一个return true;return false; 从你的.then()处理程序,但是你永远不会做任何事情的返回值,因为没有后续的.then()处理程序和承诺本身不返回。

 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; } ); } 

我build议改变这个来回报这样的承诺:

 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; } ); } 

然后,向.onOff()的调用者提供truefalse返回的promise值。 或者,如果你不需要得到那些返回的值,那么你可以删除return truereturn false语句,所以没有承诺价值。

这让我想起了一个更普遍问题的具体例子:如何从基于Promise的模型转换到传统的阻止代码?

您不要为asynchronous操作编写传统的阻止代码。 asynchronous操作是asynchronous的,永远不会是传统的阻止代码。 Promise提供了更多的结构来pipe理和协调asynchronous操作,但是您仍然需要以asynchronous的方式编写代码。 使用承诺编写asynchronous代码更容易。

JS语言增加了更多的function,例如生成器,并等待你可以用来帮助。 以下是关于该主题的简短文章: ES7asynchronous函数 。