最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Trying to use object oriented javascript and AJAX - Stack Overflow

programmeradmin3浏览0评论

I'm trying to use some Object Oriented Javascript to keep my code clean rather than have a giant messy script like usual. Using Ajax is making this plicated, with its Asynchronous nature, its difficult to separate code.

A specific problem I am having is setting object properties with Ajax.

I have the following code:

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

Class.prototype.setAttr1 = function(){
  var self = this;   
  $.ajax({
    url:'',
    success: function(data){
      self.attr1 = data.name;
    }
  });
}

This should work, but I can't really be certain that the property is set if I access it from somewhere else, correct? Is there a way to deal with that. Like if I need to use attr1 somewhere, can I wait for the ajax to return or something? Or if I'm totally off, how to people encapsulate code when using Ajax?

I'm trying to use some Object Oriented Javascript to keep my code clean rather than have a giant messy script like usual. Using Ajax is making this plicated, with its Asynchronous nature, its difficult to separate code.

A specific problem I am having is setting object properties with Ajax.

I have the following code:

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

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

This should work, but I can't really be certain that the property is set if I access it from somewhere else, correct? Is there a way to deal with that. Like if I need to use attr1 somewhere, can I wait for the ajax to return or something? Or if I'm totally off, how to people encapsulate code when using Ajax?

Share Improve this question asked Feb 23, 2015 at 14:53 DanDan 11.1k5 gold badges25 silver badges36 bronze badges 5
  • look into using callbacks. callbacks go hand-in-hand with AJAX – Ejaz Commented Feb 23, 2015 at 14:56
  • asynchronous code should never have an effect on OOP code, in any language. – Stephan Bijzitter Commented Feb 23, 2015 at 14:56
  • Out of curiousity, what do you think the line this.attr1; does in your Class function? – T.J. Crowder Commented Feb 23, 2015 at 14:57
  • Some argue, ajax callbacks in fact simplify OO approaches in JS - you create an object right upon the pletion of an ajax call. If you need synchronisation between ajax calls, use promises (eg. perjQiery's Deferred objects). – collapsar Commented Feb 23, 2015 at 14:59
  • I had been using callbacks in other areas, but this is a class attribute that could potentially used all over. I think deferreds and promises are what I'm looking for. – Dan Commented Feb 23, 2015 at 15:07
Add a ment  | 

3 Answers 3

Reset to default 6

This should work, but I can't really be certain that the property is set if I access it from somewhere else, correct?

Correct

Is there a way to deal with that. Like if I need to use attr1 somewhere, can I wait for the ajax to return or something?

Yup: Where you want to use attr, have the accessor accept a callback (directly, or indirectly by returning a promise), and have it call the callback (or resolve the promise) when the attribute is available.

It looks like you want to keep the code that initiates the ajax call separate from the code that uses the attribute value later. If so, a promise-based mechanism will probably be more useful in this situation. As you're using jQuery, here's a jQuery example using jQuery's Deferred and Promise:

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

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

Usage:

// 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);
});

Unfortunately, jQuery's Deferred/Promise implementation has an issue that most promises libraries don't: The callback you pass then will sometimes be called asynchronously, other times synchronously. (Specifically: If the promise is already resolved, the callback is synchronous.) Either just keep that in mind when using it, or use a different promise implementation.

Typically, you would either:

  • Pass around callbacks or promises which would let your code wait for the values to be set; the jQuery framework makes heavy use of callbacks, but also returns promises from its AJAX functions.

  • Have your objects raise events when attributes are changed. Backbone is a great example of a framework which makes heavy use of events.

Pass the code that needs to work with attr1 as a callback:

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

评论列表(0)

  1. 暂无评论