2016-03-21 21 views
0

tetiklenir sonra bir şeyler yapın. Katman üzerinde, tabakanın features yüklemesi tamamlandığında ateşlenen bir olay var. Bu süreç asenkrondir.Promise.all() - Birden fazla olay dinleyicileri bir <code>layer</code> nesnesi uygulamak bir kartografik API kullanıyorum

Her haritanın katmanlarının özellikleri yüklendiğinde anı işlemek için Promise kullanmak istiyorum. Ancak bazen katmanın özelliklerini önceden dinleyiciye eklemeden ve bazen de yüklemeden önce yüklenir.

aşağıda gibi Promise.all() kullanmaya çalışıyorum, ancak onun iyi yolu yapmak ne çalışıyorum elde etmek olmadığından emin değilim.

var layers = [layer1, layer2, layer3]; 
var promises = []; 

Promise.all(promises).then(function() { 
    //here am I sure that all layers features are loaded? 
    doSomething(); 
}); 

layers.forEach(function(layer) { 
    if (layer.features.length > 0) { 
     //features are already loaded 
     onFeaturesLoaded(); 
    } else { 
     //features not loaded yet, a one time event listener is added 
     layer.addOneTimeEventListener(layer.EVENTS.FEATURES_LOADED, onFeaturesLoaded, layer); 
    } 
}); 

function onFeaturesLoaded() { 
    return new Promise(function(resolve) { 
     resolve(); 
    }); 
}; 
+1

Bana iyi görünüyor. Birçok kez böyle bir kod yazdım ve hiç bir sorunum olmadı. Dikkat edilmesi gereken tek şey (ve eğer bir API sorununuzu çözmemek için API'nızı bilmiyorum) bir şey ters giderse ne olur? Sözü reddedebileceğiniz bir hata olayı var mı? Şu anda "FEATURES_LOADED" bir sebepten ötürü kovulmadığı takdirde kodunuz asılacaktır. Kullanıcıyı bir hata hakkında uyarmanın hiçbir yolu yoktur. Ama belki de bu kodunuzun başka bir yerinde ele alınır. Sadece dikkat edilmesi gereken bir şey. – dman2306

+1

Aslında ben, 'Promise.all' dediğiniz anda vaatler dizisi boş, yalan söyledim. Etkinlik işleyicinizde “yeni Promise” yapmak yerine, önceden vaatlerinizi yaratmanız, diziden doğru sözü vermeniz gerekecektir. Şu anda bunun hemen geri döneceğinden şüpheleniyorum. Konseptiniz gayet iyi, sadece sözleri beklediğinizden emin olmak için rafine edilmesi gerekiyor. – dman2306

cevap

2

Bu, Promise.all tam olarak geçerli bir kullanımı gibi görünüyor.

Unutulmaması gereken bir şey: senin forEach döngü böylece Promise.all üzerlerinde çalışabilir addEventListener durumunda sözler dönmek gerekir.

map()'u kullanmak sizin için biraz daha kolay olabilir, çünkü Promise.all numarasına geçiş yapmak için güzel bir Dizi kullanabilirsiniz. Size zaten yüklü olanlar için hemen çözmek yüklemek için henüz katmanları ve vaatler için vaat dizisi verecektir

Promise.all(layers.map(function(layer){ 
    if(layer.features.length === 0){ 
     return new Promise(function(resolve, reject){ 
      layer.addEventListener(layer.EVENTS.FEATURES_LOADED, function(){ resolve(); }, layer); 
     }); 
    } 
    else{ 
     return new Promise(function(resolve, reject){ resolve(); }); 
    } 
}) 
.then(function(){ 
    // Everything is loaded at this point. 
}); 

.

+0

Not, bu, her çalıştırıldığında ve hiçbir zaman kaldırılmamış bir olay dinleyicisi ekler gibi görünüyor. Buna bir kereden fazla denirse, bu olay dinleyicileri yığılacaktır. – jfriend00

+0

haklısınız ama ben otomatik –

+3

'yeni Promise dönmek ateş edildikten sonra dinleyiciyi kaldırmak özel addOneTimeEventListener fonksiyonunu kullanıyorum jfriend00 @ (fonksiyonu (gidermek reddetmek) {çözmek();});' Promise 'özdeş görünmektedir. çözmek() '. –

1

A biraz değiştirilmiş ve kurutma cevap @ Ajm çözümüyle dayalı:

Promise.all(layers.map(function(layer){ 
    return new Promise(function(resolve, reject) { 
     if(layer.features.length === 0) { 
      layer.addOneTimeEventListener(layer.EVENTS.FEATURES_LOADED, function(){ resolve(); }, layer); 
     } else { 
      resolve(); 
     } 
    }); 
})) 
.then(function(){ 
    // Everything is loaded at this point. 
});