我正在与ZWave服务器交互以打开和关闭灯.该交互采取以下形式:向控制ZWave网络的服务器发出http请求.我正在使用Promises,因为通过http进行交互的异步性质.
在我的程序的一个级别,我定义了以下类方法:
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标识的特定光,然后返回该请求的结果.
从Switch类方法调用onOff(),表示特定的灯光,如下所示:
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',state,error ) ); return false; } ); }
‘return true’和’return false’语句是我试图结束Promise链的尝试.但它不起作用,我仍然收到警告.
这让我觉得这是一个更普遍的问题的具体例子:你如何从基于Promise的模型转向传统的阻塞代码?
编辑
从评论中回答几个问题……
我正在使用蓝鸟.
zWave.onOff()返回一个promise.
Switch.onOff()和zWave.onOff()是不同类中的不同函数.
所有代码都是javascript.
编辑2
我相信我已经实现了jfriend00的建议,虽然我在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)',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',state ) ); return true; } ) .catch( function( error ) { winston.info( sprintf( '%s: error while turning %s => %s',error ) ); return false; } ); }
以下是警告的内容:
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)
抱歉有关格式化警告的运行,我似乎无法获得stackoverflow来正确分隔行.
解决方法
在您公开的代码中,您没有显示任何类似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)',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)',level)).then(function (value) { return(value == 'null'); }); };
这里没有必要创建一个新的承诺,因为你已经拥有了一个可以返回的承诺.您可以阅读有关避免使用here的反模式类型的更多信息.
并且,另一个可能的问题是,您在此处创建返回承诺值,但不要从方法this.onOff返回它.你明确地做了一个返回true;或者返回false;来自你的.then()处理程序,但是你永远不会对该返回值做任何事情,因为没有后续的.then()处理程序,并且不会返回promise本身.
this.onOff = function( turnOn ) { var state = turnOn ? 'ON' : 'OFF'; var self = this; zWave.onOff( this.nodeNumber,error ) ); return false; } ); }
我建议改变它以返回这样的承诺:
this.onOff = function( turnOn ) { var state = turnOn ? 'ON' : 'OFF'; var self = this; // ===== add return statement here return zWave.onOff( this.nodeNumber,error ) ); return false; } ); }
然后,它向.onOff()的调用者提供true或false返回的promise值.或者,如果您不需要获取这些返回的值,那么您可以删除返回true并返回false语句,因此没有promise值.
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?
您不会为异步操作编写传统的阻塞代码.异步操作是异步的,永远不会是传统的阻塞代码. Promise为管理和协调异步操作提供了更多的结构,但您仍然必须以异步方式为它们编写代码.使用promises编写异步代码更容易.
JS语言正在添加更多功能,例如生成器和等待,您可以使用它们来帮助解决这个问题.这是关于该主题的简短文章:ES7 async functions.