I'm working on a data synchronization service that is pulling down data from a web service and then storing it in IndexedDB.
I'm doing something like this in my TypeScript Angular Service:
this.http
.post(postUrl, postData)
.success((data: any, status, headers, config) => {
console.log("post success");
console.log("results:");
console.log(data);
var records = data.Records;
var promiseStack = [];
for (var i = 0; i < records.length; i++) {
var element = records[i];
var key = this.dataService.getKeyFromElement(objectStoreConfig, element);
console.log("key: " + key);
this.dataService.keyExists(objectStoreConfig, key).then((update) => {
if(update){
// TODO: put
promiseStack.push(true);
} else {
console.log("using dataService to add to objectStore...");
console.log("adding: " + key);
this.dataService.add(element, objectStoreConfig).then((result) => {
promiseStack.push(result);
});
}
});
}
this.q.all(promiseStack).then((result) => {
console.log("done adding/updating all.");
deferred.resolve(result);
});
})
.error((data, status, headers, config) => {
});
I am getting a post success
in the console, along with each returned record
key
that I anticipate. The trouble is with the asynchronous calls to my DataService
. The this.dataService.add
function is what actually creates a transaction and adds records to IndexedDb.
The output in my console (and in the state of IndexedDB - has just one record with a key of 188
) indicates that this code sample only calls the add
function on my DataService
for the last element in records
.
Console output:
post success
results:
Object
key: 78
key: 194
key: 188
done adding/updating all.
using dataService to add to objectStore...
adding: 188
using dataService to add to objectStore...
adding: 188
using dataService to add to objectStore...
adding: 188
How can I structure my code differently to make the for loop "wait" for each asynchronous call to be done?
Approach 1 (only works if you are targeting ES6)
if you are using TypeScript 1.5 you can just use
let
instead ofvar
to declare your element and key variables:The problem is that
element
andkey
are on the scope of the function not the for loop so every time the for loop iterates it is just replacingelement
andkey
variables instead of creating new variables. If you uselet
then the variables will be on the scope of the for loop.See What's-new-in-TypeScript for more details.
Approach 2
Alternatively you could also use Array.forEach instead of a for loop as that would also fix the scoping problem: