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 model = new GridModel();调用ajax请求。 问题是,如果我添加一个调试器; var model = new GridModel()之后的语句; 它失败。 此外,ajax请求中的调试器语句不会触发,但是如果我在var model = new GridModel()之后删除调试器语句; 然后ajax开火,我可以调试请求。 为什么它使用额外的调试器失败,是因为var GridModel是一个Expression。

基本上我想要做的是创建一个我可以调用的声明函数,当ajax请求完成后,我返回observableArray我。 如果我改变这样的function

  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(param1,param2),期望myitems现在将保存ajax请求的结果。 我只是不完全理解代码执行流程是如何工作的,如果有人可以解释为什么底层函数不起作用以及如何让它工作我会很感激。

谢谢,丹

如果您有异步操作(如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); 

$.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