Javascript 你能用Nodejs中的承诺替换事件吗?

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

我们正在使用事件管理nodejs应用程序中的工作流。我在想,我们是否可以用承诺来代替事件?我认为事件非常类似于回调,其中事件名类似于要调用的函数名,因此切换到Promissions可以吗?需要有经验的人对此发表意见

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。我用代码示例编辑了这个问题。一定要让我知道你的观点。非常感谢。