Reputation: 1541
I thought I had this working, but I think I just got lucky with a fast database lookup on my first try. The second one returns more data and fails.
So. Simple setup is a view and viewmodel. Let's call them view1.
view1.js uses require to load in dependent subviews, subview1 and subview2. Let's say subview1 is for display a list of customers and subview2 is for displaying a list of products. I've got these in separate subviews as they will be used elsewhere on other pages that also need customer lists or product lists and I don't want to have to keep recreating the same code.
Both subviews are structured like this:
define(['services/datacontext'], function (datacontext) {
var customerList= ko.observableArray();
var getCustomerList= function () {
var workingList = [];
//do some sorting and processing on the customerList array
//do stuff here
customerList(workingList);
};
var activate = function () {
//get customers!
return datacontext.getCustomers(customerList).then(getCustomerList());
};
var vm = {
activate: activate,
customerList: customerList,
};
return vm;
});
In the main view1.js (which is directly called by shell.js so the activate method fires automatically) I have this:
(I have both subviews referenced in my "define" setup)
var activate = function () {
subview1.activate(); //set up customers
subview2.activate(); //set up products
//do some other datacontext calls for stuff used directly and only in view1
};
//other code in here...
var vm = {
activate: activate,
customerList: subview1.customerList,
productList: subview2.productList
};
and in view1.html I just have standard knockout bindings like "foreach: customerList", etc.
I end up with nothing in my product List (1320 products) whereas my customer list (66 customers) more often than not works ok. If I use chrome debug and step through it appears to me that the subview1 "activate" method fires fine as I have a stop point there. The next stop point in datacontext is also hit, but then it goes wrong. On my datacontext query I have this:
var getCustomers = function (customersObservable, forceRemote) {
if (!forceRemote) {
var p = getLocal('Customers', orderBy.customer);
if (p.length > 0) {
customersObservable(p);
//resolves the promise created when calling getCustomers
return Q.resolve();
}
}
var query = EntityQuery.from('customer')
.orderBy(orderBy.customer);
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (groupsObservable) {
groupsObservable(data.results);
}
log('Retrieved customers from remote data source',
data, true);
}
};
And the problem seems to be that the promise resolves too early. My stop point in subview1 "getCustomerList" which is supposed to be fired once the datacontext "getCustomers" is finished is hit BEFORE the stop point I've put on "querySucceeded".
Have I done something wrong in the setup? Logically it seems right to me, but obviously I'm not yet up to speed on how promises work/resolve in Durandal and something is making things happen in an unexpected order from my point of view! All the data I expect are returned, it just happens AFTER the call to "getCustomerList" in subview1 which is where I need the object so I can process it. At the time the processing runs, there's nothing in the object so I get nothing displayed.
Upvotes: 1
Views: 763
Reputation: 8520
Return a promise from your main activate
function if you want the activation of the main view to wait for the sub views' getCustomers
function to complete.
for example,
//in view1.js
var activate = function () {
return $.when(
subview1.activate(), //set up customers
subview2.activate() //set up products
).then(function(){
//do some other datacontext calls for stuff used directly and only in view1
});
};
Upvotes: 1