给定jQuery中的回调模式和观察者模式,哪一个更受欢迎?

时间:2014-03-26 09:36:25

标签: javascript jquery

我试图围绕回调和事件。每种都有两种常见的模式。哪一个被认为是最佳实践,为什么?

我有callback-oriented piece of code如下:

$(function() {
  console.log('Document ready');
  getData();
})

function getData(){

  var url = "http://ip.jsontest.com/";  

  $.ajax({
      dataType: "json",
      url: url,
      success: function(data){
        buildElements(data, writeData)
      }
  });
}

function buildElements(data, callback) {
  $('div.foo').append("<div class='bar'></div>");
  callback(data);
}

function writeData(data){
  $('div.bar').append('<p>Your IP is ' + data.ip + '</p>');
}

然后event-oriented piece of code(遵循观察者模式)如下:

$(function() {
  console.log('Document ready');
  getData();
})

function getData(){

  var url = "http://ip.jsontest.com/";  

  $.ajax({
      dataType: "json",
      url: url,
      success: function(data){
        $('div.foo').trigger('getDataDone', data);
      }
  });
}

//build elements
$('div.foo').on('getDataDone', function(event, data) {
  $('div.foo').append("<div class='bar'></div>")
  $('div.foo').trigger('elementsBuilt', data);
})

//write data
$('div.foo').on('elementsBuilt', function(event, data) {
  $('div.bar').append('<p>Your IP is ' + data.ip + '</p>');     
}) 

2 个答案:

答案 0 :(得分:1)

面向事件提供了更松散的耦合,因此它有好处,但同时更难跟踪系统的哪些部分进行通信,因此您可能不想开发一些工具来记录和检查哪些工具系统的组件发出事件并对事件做出反应。

您可能希望保留一些关于哪些组件可以附加事件处理程序的规则。我已经看到,最好不要在叶子组件中附加事件,并在父母那里调用事件来调用适当的孩子的方法。

你可能不想看看承诺。它比回调更松散,但同时它们明确地传递给你的代码,所以只需查看源代码就可以更容易地跟踪发生的事情。

承诺示例:

$(function() {
  console.log('Document ready');
  gettingData()
    .done(function(data) {
      buildingElements(data)
        .done(writeData);
    });

//// alternatively:
//gettingData()
//.then(buildingElements)
//.done(writeData);
})

function gettingData(){

  var url = "http://ip.jsontest.com/";  

  // $.ajax returns a promise
  return $.ajax({
      dataType: "json",
      url: url
  });
}

function buildingElements(data) {
  $('div.foo').append("<div class='bar'></div>");

  // returns immediately resolved promise, but it could return a promise but resolve it asynchronously later
  return $.Deferred().resolve(data).promise();
}

function writeData(data){
  $('div.bar').append('<p>Your IP is ' + data.ip + '</p>');
}

jsFiddle

答案 1 :(得分:1)

回调模式的某种程序性质允许您更严格地定义程序流程。逻辑将是:

  • 做点什么
  • 当它完成时(它可以应用于ajax或其他),做下一个定义的事情。

等等。这对于ajax调用非常有效,因为执行路径很容易维护。

观察者模式可以允许多个侦听器对事件进行操作(他们正在观察更改)。所以它看起来像:

  • 做点什么
  • 当它完成时,举起事件并忘掉它
  • 观察员会做出反应并从那里拿走

因此,在您的观察者示例中,您可以轻松地拥有更多.on('elementsBuilt')并且可以相对同时执行大量其他操作。非常适合观察者活跃并在完全随意的时间死亡。

就最佳实践而言,这取决于您要实现的目标。如果您需要更加定义的解决方案,而您通常希望一次只执行一个操作,请转到回调模式路径。如果您需要在不同的地方发生多件事情,并且您特别不关心谁先处理事件的顺序,请转到观察者模式路线。