尝试使用面向对象的JavaScript和AJAX技术

4
我正在尝试使用面向对象的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时如何封装代码?


研究使用回调函数。回调函数与AJAX密不可分。 - Ejaz
异步代码在任何语言中都不应该对面向对象编程的代码产生影响。 - Stephan Bijzitter
只是出于好奇,你认为在你的“Class”函数中,this.attr1;这一行代码是做什么用的? - T.J. Crowder
有人认为,Ajax回调实际上简化了JS中的面向对象方法 - 你可以在Ajax调用完成后立即创建一个对象。如果您需要在Ajax调用之间进行同步,请使用Promises(例如perjQiery的“Deferred”对象)。 - collapsar
我在其他领域一直在使用回调函数,但这是一个类属性,可能会在各个地方使用。我认为延迟对象和承诺对象是我正在寻找的东西。 - Dan
3个回答

6

这应该可以工作,但如果我从其他地方访问它,无法确定属性是否设置正确,对吗?

是的。

有没有办法解决这个问题。比如说,如果我需要在某个地方使用attr1,我可以等待ajax返回或者其他什么东西吗?

可以:在你想要使用attr的地方,让访问器接受一个回调函数(直接或间接通过返回一个承诺),并在属性可用时调用回调函数(或解决承诺)。

看起来你想将启动ajax调用的代码与稍后使用属性值的代码分开。如果是这样,基于承诺的机制可能在这种情况下更有用。由于你正在使用jQuery,这里有一个使用jQuery的例子,使用jQuery的DeferredPromise

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实现存在一个大多数Promise库都没有的问题:你传递给then的回调函数有时会异步地调用,有时会同步地调用。(具体来说,如果Promise已经resolved,回调将是同步的。)在使用它时要记住这一点,或者使用另一个Promise实现。

1
这是一些有用的信息。非常感谢!我想我需要阅读 Promise 的文档。 - Dan

2

通常情况下,您可以:

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

  • 当属性更改时,使您的对象引发事件。Backbone是一个很好的例子,它大量使用事件。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接