在Javascript中实现解耦代码/回调的正确方法是什么?

时间:2012-08-28 16:43:08

标签: javascript callback observer-pattern

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

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

我想解决这个问题,好像B.Bar()正在做它的工作,并且不打算知道B.Bar()或任何其他可能想要标记它的函数。换句话说,插件支持未来的开发人员。

如何使用Javascript中的观察者或基于事件的回调设计模块化,非耦合代码?

2 个答案:

答案 0 :(得分:2)

这取决于您的场景是否真的是本质上的事件,或者更多是异步操作:

基于事件

使用类似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);

如果您需要执行更复杂的操作,例如过滤事件,映射事件等.Reactive Extensions(基于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();

使用控制流程库

控制流库(可以说是承诺是这种情况的一种特殊情况)旨在帮助您构建基于回调系统的操作。

答案 1 :(得分:0)

Dojo允许您收听函数调用。

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