2013-02-01 126 views
0

我已經閱讀了關於函數表達式與聲明,回調,提升的分配,並且我得到了大多數這個概念的總體思路,但是我想我無法完全理解這個概念,因爲下面的代碼,讓我發佈代碼,然後提出真正的問題。javascript代碼執行和ajax異步

var url = "beverages.txt"; 


    var GridModel = function() { 
     this.items = ko.observableArray(); 
     var me = this; 
     $.ajax({ 
      datatype: 'json', 
      url: "beverages.txt" 
     }).done(function (data) { 
      debugger; 
      var jsonData = $.parseJSON(data); 
      me.items(jsonData); 
     }); 
    }; 


    var model = new GridModel(); 

    // prepare the data 
    var source = 
    { 
     datatype: "observablearray", 
     datafields: [ 
      { name: 'name' }, 
      { name: 'type' }, 
      { name: 'calories', type: 'int' }, 
      { name: 'totalfat' }, 
      { name: 'protein' }, 
     ], 
     id: 'id', 
     localdata: model.items 
    }; 

    var dataAdapter = new $.jqx.dataAdapter(source); 

    $("#grid").jqxGrid(
    { 
     width: 670, 
     source: dataAdapter, 
     theme: 'classic', 
     columns: [ 
      { text: 'Name', datafield: 'name', width: 250 }, 
      { text: 'Beverage Type', datafield: 'type', width: 250 }, 
      { text: 'Calories', datafield: 'calories', width: 180 }, 
      { text: 'Total Fat', datafield: 'totalfat', width: 120 }, 
      { text: 'Protein', datafield: 'protein', minwidth: 120 } 
     ] 
    }); 

    ko.applyBindings(model); 
}); 

好了,所以這個代碼工作正常,它調用的VAR =新GridModel Ajax請求();.問題是,如果我添加一個調試器; var model = new GridModel();之後的語句它失敗。另外,ajax請求中的調試器語句不會觸發,但是如果我在var model = new GridModel()後刪除調試器語句,然後Ajax火災,我可以調試請求。爲什麼它使用額外的調試器失敗,是因爲var GridModel是一個表達式。

基本上我想要做的是創建一個聲明函數,我可以調用,當ajax請求完成時,我返回observableArray我。如果我改變這樣

function GridModel (param1,param2) { 
      this.items = ko.observableArray(); 
      var me = this; 
      $.ajax({ 
       datatype: 'json', 
       url: "beverages.txt" 
      }).done(function (data) { 
       debugger; 
       var jsonData = $.parseJSON(data); 
       me.items(jsonData); 
      }); 
      return me 
     }; 

的功能,那麼我想只能夠調用這樣的VAR myitems = GridModel(參數1,參數2)與期望功能myitems現在將舉行AJAX的結果請求。我只是不完全理解代碼執行流程是如何工作的,如果有人可以解釋底層函數不起作用的原因以及如何讓它起作用,我將不勝感激。

感謝, 丹

+0

它怎麼失敗異步做些什麼? – SLaks

回答

3

如果你有一個異步操作(如Ajax請求),以及其他一切依賴於它的結果,從回調恢復你的程序的流程。您不能使用return語句,它僅適用於同步代碼。

您可能需要修改您的GridModel構造方法來回調作爲參數:

var GridModel = function (callback) { 
    this.items = ko.observableArray(); 
    $.ajax({ 
     datatype: 'json', 
     url: "beverages.txt" 
    }).done(callback); 
}; 

然後在回調中恢復您的程序流程:

function resumeMyProgramFlow(data) { 
    // Now you can use the data, resume flow from here 
    debugger; 
    var jsonData = $.parseJSON(data); 
    model.items(jsonData); 
    // etc. 
} 

和實例GridModel是這樣的:

var model = new GridModel(resumeMyProgramFlow); 
+0

我想我明白你在說什麼,我只是在代碼中試過,但我遇到了同樣的問題。 var model = new GridModel(resumeMyProgramFlow);模型是一個空的對象。另外,如果我在var model = new GridModel(resumeMyProgramFlow)之後添加調試器語句;那麼Ajax從不執行。對不起,我不明白,謝謝你的幫助! – dan

+0

模型將是一個空的GridModel實例,裏面有一個空的observableArray。我不確定Ajax請求是否被調試器保存,但情況可能如此。我原來的代碼有一個錯誤,我剛修復。除此之外,我認爲所有其他代碼(在var模型之後)都應該在回調中進行。 – bfavaretto

+0

模型在回調中,因此尚未定義。試圖找出現在並按照您的建議將代碼放入回調中 – dan

2

$.ajax(...).done(...)返回,程序流程繼續。

但ajax調用還沒有完成,因爲在後臺它發送數據到服務器並等待響應。這是異步部分。當響應最後從服務器到達,在.done(...)部分執行

function (data) { 
    debugger; 
    var jsonData = $.parseJSON(data); 
    me.items(jsonData); 
} 

這是和當處理返回的數據。

你用var myitems = GridModel(param1,param2)描述的是一個同步方法。它調用服務器停止進一步處理,並且等待作爲響應。

雖然這是可能的,但它也會阻止整個程序流程。這就是爲什麼ajax調用是異步的,並且在回調函數中處理了響應。

你想要做同步

var myitems = GridModel(param1,param2); 
// do something with myitems 

是這樣

$.ajax(...).done(function(data) { 
    // 1. do something with myitems 
}); 

// 2. this will run usually *before* number 1. above 
+0

好的,有道理。我試圖完成的是使var GridModel =函數更通用,以便我只定義了一個函數,可以將參數傳遞給諸如返回ko可觀察數組然後可以傳入源,源的url目前是硬編碼,但我也會有一個函數返回我想在model.items中傳遞的源代碼。希望這是有道理的 – dan

+0

@dan我試着用一些代碼來解釋它。請參閱最新的答案。 –

+0

謝謝,是的,我明白,我試圖不必把我所有的代碼放在done函數中,謝謝你的解釋 – dan