Reputation: 5291
I am doing an async cross domain call with authentication.
When I have authenticated I retrieve the real application data with a generic get method:
define(['jquery'], function ($) {
return {
get: function (url, data) {
// Call to authenticate before retrieve data
$.ajax({
type: 'POST',
url: 'root/authentication',
data: { user: root: password: root },
dataType: 'json',
xhrFields: {
withCredentials: true
},
complete: function (response) {
// Call to retrieve application data
$.ajax({
beforeSend: function (xhr) {
xhr.withCredentials = true;
},
type: 'GET',
url: root + url,
xhrFields: {
withCredentials: true
},
async: true,
dataType: 'json',
crossDomain: true
});
}
});
}
};
});
the above data call is called by another non-generic code:
define(['cors'],
function(cors) {
return function CustomerService() {
function getCustomers() {
return cors.get('/customers');
}
return {
getCustomers: getCustomers
};
};
})
In my knockoutjs viewmodel I want to do this:
When the asyc call is made execute the renderCustomers function and update the UI.
$.when(customerService.getCustomers())
.done(renderCustomers)
.fail();
function renderCustomers(customers) {
// Add data to knockout observables
}
What do I have to change that I get my customers into the renderCustomers function?
Right now customers is undefined and I guess thats because my ajax call is not correctly setup for the promise.
Upvotes: 0
Views: 568
Reputation: 3542
In your first snippet, your Ajax call does not do anything with the customer data on success. Try this:
define(['jquery'], function ($) {
return {
get: function (url, data) {
var result = $.Deferred(); // create a deferred object to return
$.ajax({
type: "POST",
url: 'root/authentication', // you had a typo here
data: { user: root: password: root },
dataType: 'json',
xhrFields: {
withCredentials: true
},
complete: function (response) {
// Call to retrieve application data
$.ajax({
beforeSend: function (xhr) {
xhr.withCredentials = true;
},
type: "GET",
url: root + url,
xhrFields: {
withCredentials: true
},
async: true,
dataType: 'json',
crossDomain: true
}).done(function(responseData){
// resolve the manually created deferred object, and send it the customer data
result.resolve(responseData);
});
}
});
return result; // return your deferred object
}
};
});
Note that calling 'done' on ajax is the same as calling 'success.' By returning the Deferred, you'll be able to use cors.getCustomers() as a deferred itself.
You can refactor your final snippet to remove the 'when' call and use the deferred from getCustomers directly and bind your knockout there:
customerService
.getCustomers() // this returns an deferred now so you can add done and fail events
.done(function(customers) {
// Add data to knockout observables
var elem = document.getElementById('myelement');
ko.applyBindings(customers,elem);
});
Upvotes: 1