试图使用面向对象的JavaScript和AJAX

时间:2015-02-23 14:53:21

标签: javascript ajax oop

我试图使用一些面向对象的Javascript来保持我的代码干净,而不是像往常一样有一个巨大的凌乱脚本。使用Ajax使其变得复杂,具有异步特性,难以分离代码。

我遇到的一个具体问题是使用Ajax设置对象属性。

我有以下代码:

var Class = function(){
  this.attr1;
}

Class.prototype.setAttr1 = function(){
  var self = this;   
  $.ajax({
    url:'http://api.something.com?get=somedata',
    success: function(data){
      self.attr1 = data.name;
    }
  });
}

这应该可行,但如果我从其他地方访问该属性,我无法确定该属性是否已设置,对吗?有没有办法解决这个问题。就像我需要在某个地方使用attr1一样,我可以等待ajax返回还是什么?或者,如果我完全关闭,那么在使用Ajax时人们如何封装代码?

3 个答案:

答案 0 :(得分:6)

  

这应该可行,但如果从其他地方访问该属性,我无法确定该属性是否已设置,是否正确?

正确

  

有没有办法解决这个问题。就像我需要在某处使用attr1一样,我可以等待ajax返回吗?

Yup:你想在哪里使用attr,让访问者接受一个回调(直接或通过返回一个promise来间接),让它在属性可用时调用回调(或解析promise)

看起来您希望将启动ajax调用的代码与稍后使用该属性值的代码分开。如果是这样,基于承诺的机制在这种情况下可能会更有用。当你使用jQuery时,这是一个使用jQuery的DeferredPromise的jQuery示例:

var Class = function(){
  this.attr1LoadDeferred = $.Deferred();
}

Class.prototype.setAttr1 = function(){
  var self = this;   
  $.ajax({
    url:'http://api.something.com?get=somedata',
    success: function(data){
      self.attr1 = data.name;
      self.attr1LoadDeferred.resolveWith(self);
    }
  });
}
Class.prototype.accessAttr1 = function() {
    return this.attr1LoadDeferred.promise();
};

用法:

// Create an instance
var c = new Class();

// At some point, initiate loading the value
c.setAttr1();

// At some point, look to use the value
c.accessAttr1().then(function(inst) {
    console.log(inst.attr1);
});

// Somewhere else, look to use the value
c.accessAttr1().then(function(inst) {
    doSomethingElseWith(inst.attr1);
});

不幸的是,jQuery的Deferred / Promise实现有一个问题,大多数承诺库都没有:你传递的回调then 有时异步调用,其他时间同步。 (具体来说:如果promise已经解决,则回调是同步的。)要么在使用它时要记住这一点,要么使用不同的promise实现。

答案 1 :(得分:2)

通常,你会:

  • 传递回调或承诺,让您的代码等待设置值; jQuery框架大量使用回调,但也从其AJAX函数返回promise。

  • 让属性在更改属性时引发事件。 Backbone是一个很好地利用事件的框架的一个很好的例子。

答案 2 :(得分:1)

将需要使用attr1的代码作为回调传递:

Class.prototype.setAttr1 = function(callback){
  var self = this;   
  $.ajax({
    url:'http://api.something.com?get=somedata',
    success: function(data){
      self.attr1 = data.name;
      if (callback)
        callback(self);
    }
  });
}