javascript - Döngü içindeki Promiseler: TypeScript + Angular + IndexedDB
Web servisinden veri çeken ve ardından bunu IndexedDB'de saklayan bir veri senkronizasyon servisi üzerinde çalışıyorum.
TypeScript Angular Servisimde böyle bir şey yapıyorum:
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) => {
});
Konsolda, beklediğim her dönen record key ile birlikte bir post success alıyorum. Sorun, DataService ile yaptığım eşzamanlı olmayan (asenkron) çağrılarda. this.dataService.add fonksiyonu aslında bir işlem oluşturur ve kayıtları IndexedDb'ye ekler.
Konsolumdaki çıktı (ve IndexedDB durumunda - sadece 188 anahtarıyla bir kayıt var) bu kod örneğinin yalnızca records içindeki son öğe için DataService üzerindeki add fonksiyonunu çağırdığını gösteriyor.
Konsol çıktısı:
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
Asenkron çağrının tamamlanmasını beklemesi için döngüyü farklı şekilde nasıl yapılandırabilirim?
Cevap #1
Yaklaşım 1 (sadece ES6 hedefliyorsanız çalışır)
Eğer TypeScript 1.5 kullanıyorsanız, öğe ve anahtar değişkenlerinizi tanımlamak için var yerine sadece let kullanabilirsiniz:
let element = records[i];
let key = this.dataService.getKeyFromElement(objectStoreConfig, element);
Sorun, element ve key'in fonksiyonun kapsamında olması, for döngüsünde değil, bu yüzden for döngüsü her döndüğünde sadece element ve key değişkenlerini değiştirmesi, yeni değişkenler oluşturmaması. Eğer let kullanırsanız, değişkenler for döngüsünün kapsamında olur.
Daha fazla detay için TypeScript'teki Yeniliklere Bakın.
Yaklaşım 2
Alternatif olarak, kapsam sorununun düzelmesini sağladığı için bir for döngüsü yerine Array.forEach de kullanabilirsiniz:
records.forEach(function(element) {
//...
});
