Javascript:将AJAX结果保存为类变量

时间:2016-03-14 11:47:16

标签: javascript jquery ajax callback

我知道javascript不使用Class,至少不是常识。我想知道如何在类变量中返回并保存AJAX返回值,而不是在回调中调用多个方法。

var Reader = function(){
  //Initialize some variables
  this.data = null;
}

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     this.data = data;
   });
}

Reader.prototype.searchData = function(param){
   //Needs access to this.data
}
Reader.prototype.findData = function(id){
  //Needs access to this.data
}

Reader.prototype.deleteItem = function(id){
  // Needs access to this.data
}

在上面的代码中,需要在data内调用需要访问ajax success callback属性的任何函数,所以如果我有十个方法需要数据,我将不得不排除所有他们在回调中,我感觉不对。如何最小化回调中的函数数量,并以其他方式确保函数成功并将数据保存为实例变量data

13 个答案:

答案 0 :(得分:7)

最重要的部分是如何使用JavaScript处理异步数据。有一些经过良好测试的解决方案:功能和承诺。

在两个cass中,Reader应该有一个构造函数,它可以像这样分配数据:

function Reader(data) {
   this.data = data;
}

回调方法需要一个具有回调函数的工厂函数。

function getReader(url, callBack) {
   Ajax.success(function(data){
      callBack( new Reader(data) );
   });
}

并像

一样使用它
getReader(url, function(reader) {
    reader.searchData();
});

Promise -approach不需要立即回调,因此结果可以存储在变量中并作为变量传递,具有一些优势:

function getReaderPromise(url) {
   return new Promise( function( resolve, reject ) {
     Ajax.success(function(data){
      resolve( new Reader(data) );
     });    
   });
}

但是,使用promise通常需要调用promise的 then 函数:

getReaderPromise(url).then( function(reader) {
    reader.searchData();
});
// Fat arrow syntax
getReaderPromise(url).then( (reader) => {
    reader.searchData();
});  

将来你可以使用带有像

这样的产量的ES6生成器去掉Promises的回调
let reader = yield getReaderPromise( url );

如此处所述:https://davidwalsh.name/async-generators

答案 1 :(得分:4)

您可以尝试以下方式:

var Reader = function(){
  //Initialize some variables
  this.data = null;
}

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   this.data = Ajax({url: urlPath}); // return promise
}

Reader.prototype.searchData = function(param){
   //Needs access to this.data
   if(this.data){
       this.data.then(...);
   }

}
Reader.prototype.findData = function(id){
  //Needs access to this.data
   if(this.data){
       this.data.then(...);
   }
}

Reader.prototype.deleteItem = function(id){
  // Needs access to this.data
   if(this.data){
       this.data.then(...);
   }
}

答案 2 :(得分:2)

在您的代码中:

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     this.data = data;
   });
}

"这"不是Reader实例上下文,您应该将其更改为

Reader.prototype.makeAjaxCall = function(urlPath){
   var myThis = this;
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     myThis .data = data;
   });
}

在myThis变量中保持指向Reader实例的指针并访问成功函数

答案 3 :(得分:1)

这是我认为解决它的好方法,它需要几个回调但是

var Reader = function(){
  //Initialize some variables
  this.data = null;
}

Reader.prototype.makeAjaxCall = function(urlPath, cb) {
   //Make and Ajax call and return some value
   Ajax.success(function(data) {
     this.data = data;
     if(cb) cb();
   });
}

Reader.prototype.searchData = function(param){
    var self = this;
    if(!this.data) {
        // data doesn't exist, make request
        this.makeAjaxCall(urlPath, function() {
            // when is ready, retry
            self.searchData(param);
        });
        return;
    }
   // do whatever you need...
   // data exists
}
Reader.prototype.findData = function(id){
    var self = this;
    if(!this.data) {
        // data doesn't exist, make request
        this.makeAjaxCall(urlPath, function() {
            // when is ready, retry
            self.findData(id);
        });
        return;
    }
   // do whatever you need...
   // data exists
}

Reader.prototype.deleteItem = function(id){
    var self = this;
    if(!this.data) {
        // data doesn't exist, make request
        this.makeAjaxCall(urlPath, function() {
            // when is ready, retry
            self.deleteItem(id);
        });
        return;
    }
   // do whatever you need...
   // data exists
}

答案 4 :(得分:1)

你的问题是关于'this'键的混淆。

在函数中使用它时,它使用该函数的上下文。

所以这稍微使用了不同的上下文:

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     this.data = data;
   });
}

比这个:

Reader.prototype.makeAjaxCall = function(urlPath){
   var readerContext = this;
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     readerContext.data = data;
   });
}

这是解决问题的方法。

答案 5 :(得分:0)

您可以执行类似

的操作
 Reader.prototype.searchData = function(param){
    var self = this;
    if (!this.data) {
       setTimeout(function() { self.searchData(param) }, 1000);
       return;
    }
    ...
 }

答案 6 :(得分:0)

尝试改变这一点:

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     this.data = data;
   });
}

到此:

Reader.prototype.makeAjaxCall = function(urlPath){
  var _this = this;

   //Make and Ajax call and return some value
   Ajax.success(function(data){
     _this.data = data;
   });
}

答案 7 :(得分:0)

一个简单的解决方案是将所有函数调用放在另一个函数中,并仅从回调函数中调用该函数:

var Reader = function(){
  //Initialize some variables
  this.data = null;
}

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   var that = this;
   Ajax.success(function(data){
     that.data = data;
     that.makeOtherCalls();
   });
};


Reader.prototype.makeOtherCalls = function(){

    // call the functions that need this.data here

};

答案 8 :(得分:0)

您可以使用context this设置在$.ajax()回调$.ajax()处设置Reader;包括// set `this` at `$.ajax()` to context of `Reader` instance var Reader = function(context) { //Initialize some variables this.data = null; // handle `$.ajax()` errors this.err = function(jqxhr, textStatus, errorThrown) { console.log(textStatus, errorThrown, this); } this.makeAjaxCall = function(urlPath) { //Make and Ajax call and return some value return $.ajax({ url: urlPath, // set `context` to `this` context: context || this, }) .then(function(data) { this.data = data; console.log("in `Reader.makeAjaxCall`, this is:", this); }, this.err); } this.searchData = function(param) { //Needs access to this.data console.log("in `Reader.searchData`", this.data); } this.findData = function(id) { //Needs access to this.data console.log("in `Reader.findData`", this.data); } this.deleteItem = function(id) { // Needs access to this.data console.log("in `Reader.deleteItem`", this.data); } } var reader = new Reader(); reader.makeAjaxCall("") .then(reader.searchData) .then(reader.findData) .then(reader.deleteItem) .then(function() { console.log("complete", this.data, this) }) 实例中的错误处理函数。

jpa:
    properties:
      jadira.usertype.autoRegisterUserTypes: true

答案 9 :(得分:0)

人们痴迷于使用原型来在类中创建函数,但是通过使用带有'this'引用的函数,有一种更简洁的方法。然后,您可以通过自变量访问类的内部工作。

例如:

var Reader = function(){
    var self = this;

    //Initialize some variables
    this.data = null;

    this.makeAjaxCall = function(urlPath){  
       Ajax.success(function(data){
         self.data = data;
       });
    }
}

然后在原型方法中,您可以使用以下数据:

this.data

您可以使用以下方法调用ajax方法:

this.makeAjaxCall(url);

您可以使用以下方法从类外部调用ajax方法:

var myReader = new Reader();
myReader.makeAjaxCall(url);

按照正常情况。

答案 10 :(得分:0)

使用GLOBAL JS VARIABLE

您可以简单地使用全局JS变量来满足此类要求。请检查以下代码

var globalData; /* This is global.It can be accessed anywhere */
var Reader = function(){
  //Initialize some variables
  globalData = null;
}

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     globalData = data;
   });
}

Reader.prototype.searchData = function(param){
   //Access globalData here
}
Reader.prototype.findData = function(id){
  //Access globalData here
}

Reader.prototype.deleteItem = function(id){
  //Access globalData here
}

答案 11 :(得分:0)

为了将返回数据保存在所谓的Class变量中,根据您的示例,您需要了解使用this关键字的上下文。 在你的例子中

Reader.prototype.makeAjaxCall = function(urlPath){
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     this.data = data;
   });
}

this被称为Ajax对象。

由于Reader对象中的this.data几乎封装在Reader对象的上下文中,因此您需要在进行Ajax调用之前将其保存在本地,以便能够通过呼叫。 像这样:

Reader.prototype.makeAjaxCall = function(urlPath){
    var _this = this;
   //Make and Ajax call and return some value
   Ajax.success(function(data){
     _this.data = data;
   });
}

这几乎解决了上下文问题,在进行函数调用时非常有用。 一个简单的解决方案是只定义一个局部变量,您可以在其中临时存储数据,然后使用它来覆盖this.data的值。 代码应如下所示:

 Reader.prototype.makeAjaxCall = function(urlPath){
        var tempData;
       //Make and Ajax call and return some value
       Ajax.success(function(data){
         tempData = data;
       });
       this.data = tempData;
    }

答案 12 :(得分:0)

我为此开发了自己的jQuery ajax包装器,但它确实需要jQuery ...如果这有助于检查我的github repo

JQPS Framework v. 1.1b - Github

这可以帮到你很多,它使用命名空间的OOP(你正在寻找的类),比如Myobject.vars.anything = value(来自回调)

电话示例

Main.ajaxCall('auth','login','POST','TEXT',{dataObj},{Utils:{1:'setVar|Main,myVar,,callback',2:'anyOtherFunction'}},false);

这将触发对http://yoursite.com/auth/login的ajax调用,dataObj作为post对象,在回调时将调用第一个函数,在我们的例子中Utils.setVar()这将存储响应从Main.vars.myVar中的回调中我们在回调对象中定义它,之后第二个函数将按照调用Utils.anyOtherFunction()中的定义被触发和执行...你可以添加你想要的函数数量在回调中。

有关更多信息,您可以检查来自github的自述文件,这是为同步和异步调用设置的,但它确实需要jQuery,没有它就无法工作。