简体   繁体   English

NodeJS 服务层异步通信

[英]NodeJS Service Layer asynchronous communication

If I have to invoke ServiceB.action as a result of ServiceA.action being invoked, should I call ServiceB.action from ServiceA.action at the appropriate time, or should I emit an event from ServiceA and let ServiceB react to that event?如果由于调用了ServiceA.action而必须调用ServiceB.action ,我应该在适当的时间从ServiceA.action调用ServiceB.action ,还是应该从ServiceA发出事件并让ServiceB对该事件做出反应?

I can use an EventEmitter, but it works synchronously, in a sense that the callbacks are invoked sequentially without waiting the previous to resolve, which is ok for me.我可以使用 EventEmitter,但它是同步工作的,从某种意义上说,回调是按顺序调用的,而无需等待前一个解决,这对我来说没问题。 What isn't, though, is that the $emit will not wait until all of the listeners have resolved.然而,没有的是$emit不会等到所有侦听器都已解决。

For a more real world scenario, lets assume that I have a Subscription service, and when a new subscription is created, the Email service needs to know about it so that it can notify somebody by email.对于更真实的场景,假设我有一个订阅服务,当创建一个新订阅时,Email 服务需要知道它,以便它可以通过 email 通知某人。

const SubscriptionService = {
  async create(user) {
    await Subscription.create(user)
   
    // Notify email service
  }
}

const EmailService = {
    async notify(user) {...}
}

One way I could do it, is call the EmailService.notify(user) from SubscriptionService.create and pass in the user.我可以做到的一种方法是从SubscriptionService.create调用EmailService.notify(user)并传入用户。

Another way I could do it is with an event emitter我可以做到的另一种方法是使用事件发射器

async create(user) {
    await Subscription.create(user)

    Emitter.$emit('subscription', user)
}

The second approach seems clean, because I'm not mixing things together, the notifications happen as a result of the subscription being created and the create method is not polluted with extra logic.第二种方法看起来很干净,因为我没有将事情混合在一起,通知是由于创建订阅而发生的,并且 create 方法没有被额外的逻辑污染。 Also, adding more side-effects like the notification one would be simpler.此外,添加更多副作用(如通知)会更简单。

The subscription service's create method, however, will not wait until all of the listeners have resolved, which is an issue.但是,订阅服务的 create 方法不会等到所有侦听器都已解决,这是一个问题。 What if the Notification fails?如果通知失败怎么办? The user will not get the email, in this scenario.在这种情况下,用户不会得到 email。 What about error handling?错误处理呢? In the first scenario I can handle the errors on spot when I invoke the EmailService.notify , but not with the emitter.在第一种情况下,我可以在调用EmailService.notify时当场处理错误,但不能使用发射器。

Is not meant for similar use-cases or am I looking at the problem in a wrong way?不适用于类似的用例,还是我以错误的方式看待问题?

Since the create method returns a Promise, you can just do something like:由于 create 方法返回 Promise,因此您可以执行以下操作:

SubscriptionService.create(user).then((user) => EmailService.notify(user));

Note: The above depends on where and how you're calling these methods.注意:以上内容取决于您调用这些方法的位置和方式。

The event pattern is the most appropriate for the scenario you described. event模式最适合您描述的场景。 Rather than using std event emitters you could use promise-events which should let you do error handling as it seems you described.您可以使用promise-events而不是使用 std 事件发射器,它应该可以让您按照您所描述的那样进行错误处理。

Hope this helps.希望这可以帮助。

Both of the approaches are appliable and correct for specific scenarios.这两种方法都适用于特定场景并且是正确的。

Pub/Sub is great for the applications where there are few subscribers and does various jobs in the background. Pub/Sub 非常适合订阅者很少且在后台执行各种工作的应用程序。 Publishers( SubscriptionService.create ) are loosely coupled to the subscribers-( EmailService.notify )发布者( SubscriptionService.create ) 与订阅者松散耦合-( EmailService.notify )

Service layer exists for applying business logics, and nothing wrong with using function composition for more than one methods which serves for a single operation.服务层是为了应用业务逻辑而存在的,将 function 组合用于多个服务于单个操作的方法并没有错。 If it should notify user after subscription has been created, yes those two methods can work together.如果它应该在创建订阅后通知用户,是的,这两种方法可以一起工作。 Also, if you want to use EmailService.notify method in somewhere else, you have to publish a new event, and create a new subscriber for that too, because you can't just use the previously created subscriber.此外,如果您想在其他地方使用 EmailService.notify 方法,您必须发布一个新事件,并为此创建一个新订阅者,因为您不能只使用之前创建的订阅者。

Personally, I would prefer, calling ServiceB.action inside ServiceA.action on your scenario.就个人而言,我更喜欢在您的场景中调用ServiceA.action内的ServiceB.action Publishing an event and creating a subscriber in the ServiceB is looks a bit much.ServiceB中发布事件并创建订阅者看起来有点多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM