Javascript 你能用Nodejs中的承诺替换事件吗?
我们正在使用事件管理nodejs应用程序中的工作流。我在想,我们是否可以用承诺来代替事件?我认为事件非常类似于回调,其中事件名类似于要调用的函数名,因此切换到Promissions可以吗?需要有经验的人对此发表意见Javascript 你能用Nodejs中的承诺替换事件吗?,javascript,node.js,events,promise,Javascript,Node.js,Events,Promise,我们正在使用事件管理nodejs应用程序中的工作流。我在想,我们是否可以用承诺来代替事件?我认为事件非常类似于回调,其中事件名类似于要调用的函数名,因此切换到Promissions可以吗?需要有经验的人对此发表意见 add : function(req, res, next){ var workflow = req.app.utility.workflow(req, res); workflow.on('checkPermissions', function(){ // If admin
add : function(req, res, next){
var workflow = req.app.utility.workflow(req, res);
workflow.on('checkPermissions', function(){
// If admin is permitted to add Widget template
var isPermitted = permissions.getPermission(req.user.group, "widget-template", "add");
console.log("Is permitted to add WidgetTemplate:-", isPermitted);
if(!isPermitted)
workflow.emit('exception', 'Not Permitted');
else
workflow.emit('validate');
});
workflow.on('validate', function(){
if(!req.body.wID)
workflow.outcome.errfor.wID = 'required';
if(!req.body.wname){
workflow.outcome.errfor.wname = 'required';
}
if(workflow.hasErrors())
{
workflow.outcome.errfor.msg = 'Please fill all the fields';
return workflow.emit('response');
}
else
workflow.emit('add');
});
workflow.on('add', function(){
var WidgetTemplate = req.app.db.models.WidgetTemplate;
var fieldsToSet = new WidgetTemplate({
widgetTempID : req.body.wID,
name : req.body.wname,
devType : req.body.devTypes,
sensors : req.body.sensors,
properties : req.body.properties? req.body.properties : [],
multiple_devices : req.body.multiple_devices? req.body.multiple_devices : false,
added_by : req.user.id
});
console.log("FieldsToset", fieldsToSet);
fieldsToSet.save()
.then(
() => {
console.log("Widget Template created...");
workflow.emit('response');
}
)
.catch((err) => {
console.log("Some error occurred", err.code);
if(err.code == 11000)
workflow.emit('exception', 'Duplicate widget template ID');
else
workflow.emit('exception', err);
});
});
workflow.emit('checkPermissions');
}这种做法的主要缺点是承诺只能解决一次。如果您的事件属于此类,那么当然,您可以使用承诺。但许多事件都希望发生多次,而承诺并不是一种很好的表达方式
另一种选择是使用可观测数据,它与承诺类似,但可以发出任意次数的信号。它们强大而灵活,但它们确实有一条重要的学习曲线。一个流行的可观测库是rxjs:它的主要缺点是承诺只能解决一次。如果您的事件属于此类,那么当然,您可以使用承诺。但许多事件都希望发生多次,而承诺并不是一种很好的表达方式
另一种选择是使用可观测数据,它与承诺类似,但可以发出任意次数的信号。它们强大而灵活,但它们确实有一条重要的学习曲线。一个流行的可观察对象库是rxjs:事件监听器可以被一个承诺所取代,该承诺只适用于本应发出一次的事件,例如,事件发射器
一次
方法可以被承诺。否则,应创建多个承诺
解决这两种情况。它允许提示发出一次的事件:
const result = await pEvent(emitter, 'finish');
否则,它允许根据需要使用异步迭代器和等待的对承诺进行迭代:
const asyncIterator = pEvent.iterator(emitter, 'data', {
resolutionEvents: ['finish']
});
for await (const event of asyncIterator) {
console.log(event);
}
正如另一个答案所提到的,观测值是另一种可能有用的模式。可观察的事物能够以简洁为代价完成承诺所做的一切,甚至更多。由于它们可以发出多个值,因此侦听发出的事件是一个很好的用例。事件侦听器可以被替换为仅对应该发出一次的事件的承诺,例如,可以承诺事件发送器一次
方法。否则,应创建多个承诺
解决这两种情况。它允许提示发出一次的事件:
const result = await pEvent(emitter, 'finish');
否则,它允许根据需要使用异步迭代器和等待的对承诺进行迭代:
const asyncIterator = pEvent.iterator(emitter, 'data', {
resolutionEvents: ['finish']
});
for await (const event of asyncIterator) {
console.log(event);
}
正如另一个答案所提到的,观测值是另一种可能有用的模式。可观察的事物能够以简洁为代价完成承诺所做的一切,甚至更多。由于它们可以发出多个值,因此侦听发出的事件对于它们来说是一个很好的用例。可能已经回答了,但我通常是这样做的:
特别是对于indexedDb
事件包装器之类的东西,可以简化使用
除了Future
的定义之外,上述模式不需要任何库或包Future(eventFn)
是一个“一次性”事件处理程序,但它可以用于创建可重复的promisified事件处理程序,就像使用计时器一样
也就是说,在工作流程fn
中,您只需循环
即可重新应用等待未来(eventFn)
或者,您可能会发现Future
的这种变体更具通用性
class PromiseEx extends Promise {
resolve(v,...a) {
this.settled = true; this.settledValue = v;
return(this.resolve_(v,...a))
}
reject(v,...a) {
this.settled = false; this.settledValue = v;
return(this.reject_(v,...a))
}
static Future(fn,...args) {
let r,t,ft = new PromiseEx((r_,t_) => {r=r_;t=t_})
ft.resolve_ = r; ft.reject_ = t; fn(ft,...args);
return(ft)
}
}
可能已经回答了,但我通常是这样做的:
特别是对于indexedDb
事件包装器之类的东西,可以简化使用
除了Future
的定义之外,上述模式不需要任何库或包Future(eventFn)
是一个“一次性”事件处理程序,但它可以用于创建可重复的promisified事件处理程序,就像使用计时器一样
也就是说,在工作流程fn
中,您只需循环
即可重新应用等待未来(eventFn)
或者,您可能会发现Future
的这种变体更具通用性
class PromiseEx extends Promise {
resolve(v,...a) {
this.settled = true; this.settledValue = v;
return(this.resolve_(v,...a))
}
reject(v,...a) {
this.settled = false; this.settledValue = v;
return(this.reject_(v,...a))
}
static Future(fn,...args) {
let r,t,ft = new PromiseEx((r_,t_) => {r=r_;t=t_})
ft.resolve_ = r; ft.reject_ = t; fn(ft,...args);
return(ft)
}
}
如果在您的应用程序中,每个事件只能触发一次,则为是,否则为否,因为承诺结果只能解决一次。您能否提供一个示例,说明您希望替换哪些“事件”?事件发送者和观察者与承诺的想法不同。。。但有时您可以获取基于事件的对象并将其转换为承诺,也就是说,readFile可以使用事件分块,但可以一次读取整个文件。@CodyG。我用代码示例编辑了这个问题。一定要让我知道你的观点。谢谢。如果在您的应用程序中,每个事件只能触发一次,则为是,否则为否,因为承诺结果只能解决一次。您能否提供一个要替换的“事件”的示例?事件发送者和观察者与承诺的想法不同。。。但有时您可以获取基于事件的对象并将其转换为承诺,也就是说,readFile可以使用事件分块,但可以一次读取整个文件。@CodyG。我用代码示例编辑了这个问题。一定要让我知道你的观点。非常感谢。