【问题标题】:What is the correct way to implement decoupled code / callbacks in Javascript?在 Javascript 中实现解耦代码/回调的正确方法是什么?
【发布时间】:2012-08-23 05:32:26
【问题描述】:

我有几个不同的 JavaScript 对象,它们的方法要分开。但是,我需要某种类型的观察者、回调或插件设计,以便我可以在正确的时间触发这些方法。

例如,A.Foo() 应该几乎总是在 B.Bar() 之后运行 - 但我不想打电话给 A.Foo() inside B.Bar() 因为在B.Bar() 之后,它不应该运行那些奇怪的时间。那会耦合我的代码,我知道这很糟糕。

我想解决这个问题,就好像B.Bar() 只是在做它的工作,并且不打算了解A.Foo() 或任何其他可能想要与之一起标记的功能。换句话说,为未来的开发者提供插件支持。

您如何在 Javascript 中设计带有观察者或基于事件的回调的模块化、非耦合代码?

【问题讨论】:

  • 这个问题可能让我想不通,但是如果全局变量为假,您能否将A.Foo() 中的某种全局布尔变量设置为true 并让B.Bar() 立即返回?
  • @Travesty3,这会起作用 - 但它会使代码不仅耦合到这两个函数,而且还耦合到一个随机全局变量。
  • 这个问题的答案取决于你的代码结构。最通用的方法是传入一个函数来调用B.Bar()。否则这取决于你实际在做什么,你也可以使用某种延迟式机制,这样你就不需要传递它了。
  • 您介意放置一些“知名”对象,例如 A.Foo 和 B.Bar 都知道的观察者(您在原始帖子中提到过)吗?另外,您介意使用 jQuery 还是想要一个完全独立于第三方库的解决方案?
  • 类似函数链的东西?

标签: javascript callback observer-pattern


【解决方案1】:

这取决于你的场景是真正的事件,还是更多的异步操作:

基于事件

使用microevent 之类的内容,您可以执行以下操作。这种模式真的很常见也很简单,所以我建议你在某个时候自己尝试一下,因为从理解的角度来看它很棒。

MicroEvent.mixin(A);

A.Foo = function () {
  //Do stuff A needs to do, then:
  A.trigger('foo-complete');
};

//Somewhere nice and separate and decoupled
A.bind('foo-complete', B.Bar);

如果您需要执行更复杂的操作,例如过滤事件、映射事件等。反应式扩展(基于 C# 库)非常强大,但如果您不需要,这是一个可以加载的大库功能。

异步操作

使用回调

这可以使用回调来完成,这对于相当简单的操作非常有用:

A.Foo = function (cb) {
  //Do stuff A needs to do, then:
  if (cb) cb();
};

A.Foo(B.Bar);

使用承诺

这些最初看起来更复杂,但它们很容易组合,并且内置了处理错误的好方法。

使用Q 这是更流行的承诺库之一(同样,有很多):

A.Foo = function () {
  var def = Q.defer();
  setTimeout(function () {
    //Simulate async operation
    def.resolve();
  }, 1000);
  return def.promise;
};

A.Foo().then(B.Bar).end();

使用控制流库

控制流库(可以说是 Promise 的一个特例)旨在帮助您编写基于回调系统的操作。

【讨论】:

    【解决方案2】:

    Dojo 允许您监听函数调用。

    dojo.connect("foo", A, function(){
      B.bar();
    });
    

    【讨论】:

      猜你喜欢
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 2018-08-12
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      相关资源
      最近更新 更多