Reputation: 2957
I have read allot about function expressions vs declaration, callbacks, hoisting, and I get the general idea of most of this but I guess I can't quite grasp the concept because of the below code, let me post the code and then ask the real questions.
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);
});
Ok so this code works fine, it calls the ajax request by var model = new GridModel();. The problem is that if I add a debugger; statement after var model = new GridModel(); it fails. Also the debugger statements inside of the ajax request don't fire, however if I remove the debugger statement after the var model = new GridModel(); then ajax fires and I can debug the request. Why does it fail with the additional debugger, is it because var GridModel is an Expression.
Basically want I would like to do is is create a declaration function that I can call and when ajax request is done I return the observableArray me. If I change the function like this
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
};
Then I would like to just be able to call that function like this var myitems = GridModel(param1,param2) with the expectation that myitems will now hold the results of the ajax request. I just don't fully understand how the code execution flow works, If someone could explain why the bottom function doesn't work and how to get it to work I would appreciate it.
Thanks, Dan
Upvotes: 0
Views: 1055
Reputation: 74098
When $.ajax(...).done(...)
returns, the program flow continues.
But the ajax call isn't finished yet, because in the background it sends data to the server and waits for a response. This is the asynchronous part. When the response finally arrives from the server, the part in .done(...)
is executed
function (data) {
debugger;
var jsonData = $.parseJSON(data);
me.items(jsonData);
}
This is where and when the returned data is processed.
What you describe with var myitems = GridModel(param1,param2)
is a synchronous method. It calls to the server stops further processing and waits for the response.
While this is possible, it also blocks the whole program flow. That's why an ajax call is asynchronous and the response dealt with in a callback function.
What you want to do synchronously
var myitems = GridModel(param1,param2);
// do something with myitems
is done asynchronously this way
$.ajax(...).done(function(data) {
// 1. do something with myitems
});
// 2. this will run usually *before* number 1. above
Upvotes: 2
Reputation: 71939
If you have an asynchronous operation (like an Ajax request), and everything else depends on its result, resume your program's flow from the callback. You can't use return
statements, it only works for synchronous code.
You may want to modify your GridModel
constructor to take a callback as a parameter:
var GridModel = function (callback) {
this.items = ko.observableArray();
$.ajax({
datatype: 'json',
url: "beverages.txt"
}).done(callback);
};
Then resume your program flow from inside the callback:
function resumeMyProgramFlow(data) {
// Now you can use the data, resume flow from here
debugger;
var jsonData = $.parseJSON(data);
model.items(jsonData);
// etc.
}
And instantiate GridModel
like this:
var model = new GridModel(resumeMyProgramFlow);
Upvotes: 3