İşte senin yapman gerektiğini düşündüğüm şekilde.
zinciri bölmek
Her iki işlev de amazingData kullanacağından , onlara ayrılmış bir işlevde sahip olmak mantıklıdır. Bunu genellikle bazı verileri yeniden kullanmak istediğimde yapıyorum, bu nedenle her zaman bir işlev arg olarak mevcut.
Örneğiniz bazı kodları çalıştırdığı için, hepsinin bir işlev içinde açıklandığını varsayacağım. Bunu toto () olarak arayacağım . Sonra ikimiz de çalışacak başka bir işlevi olacaktır afterSomething () ve afterSomethingElse () .
function toto() {
return somethingAsync()
.then( tata );
}
Ayrıca , genellikle Promises ile gitmenin yolu olduğu için bir dönüş ifadesi eklediğimi fark edeceksiniz - her zaman bir söz verirsiniz, böylece gerekirse zincirlemeye devam edebiliriz. Burada somethingAsync () üretecek amazingData ve yeni işlev içinde her yerde mevcut olacaktır.
Şimdi bu yeni işlevin neye benzeyeceği tipik olarak processAsync () 'in de zaman uyumsuz olup olmadığına bağlıdır ?
processAsync eşzamansız değil
ProcessAsync () eşzamansız değilse, işleri aşırı karmaşık hale getirmek için bir neden yok . Bazı eski iyi sıralı kodlar bunu yapabilirdi.
function tata( amazingData ) {
var processed = afterSomething( amazingData );
return afterSomethingElse( amazingData, processed );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
AfterSomethingElse () işlevinin eşzamansız bir şey yapıp yapmadığının önemli olmadığını unutmayın . Aksi takdirde bir söz iade edilir ve zincir devam edebilir. Değilse, sonuç değeri döndürülür. Ancak işlev a then () ' dan çağrıldığı için , değer yine de bir söze sarılacaktır (en azından ham Javascript'te).
processAsync asenkron
Eğer processAsync () eşzamansızsa, kod biraz farklı görünecektir. Burada afterSomething () ve afterSomethingElse () ' nin başka hiçbir yerde yeniden kullanılmayacağını düşünüyoruz.
function tata( amazingData ) {
return afterSomething()
.then( afterSomethingElse );
function afterSomething( ) {
return processAsync( amazingData );
}
function afterSomethingElse( processedData ) {
}
}
AfterSomethingElse () için öncekiyle aynı . Asenkron olabilir veya olmayabilir. Bir söz iade edilecek veya bir değer çözülmüş bir söze sarılacaktır.
Kodlama tarzınız yapmakta olduğum şeye oldukça yakın, bu yüzden 2 yıl sonra bile cevap verdim. Her yerde anonim işlevlere sahip olmanın büyük bir hayranı değilim. Okumakta zorlanıyorum. Toplumda oldukça yaygın olsa bile. Biz yerini gibi öyle geri arama-cehennem bir tarafından söz-araf .
Ayrıca işlevleri adını tutmak ister sonra kısa. Zaten sadece yerel olarak tanımlanacaklar. Ve çoğu zaman işi yapmak için başka bir yerde tanımlanmış - çok yeniden kullanılabilir - başka bir işlevi çağırırlar. Bunu sadece 1 parametresi olan fonksiyonlar için bile yapıyorum, bu nedenle fonksiyon imzasına bir parametre ekleyip çıkardığımda fonksiyonu içeri ve dışarı almam gerekmiyor.
Örnek yemek
İşte bir örnek:
function goingThroughTheEatingProcess(plenty, of, args, to, match, real, life) {
return iAmAsync()
.then(chew)
.then(swallow);
function chew(result) {
return carefullyChewThis(plenty, of, args, "water", "piece of tooth", result);
}
function swallow(wine) {
return nowIsTimeToSwallow(match, real, life, wine);
}
}
function iAmAsync() {
return Promise.resolve("mooooore");
}
function carefullyChewThis(plenty, of, args, and, some, more) {
return true;
}
function nowIsTimeToSwallow(match, real, life, bobool) {
}
Promise.resolve () öğesine çok fazla odaklanmayın . Kararlı bir söz oluşturmanın hızlı bir yoludur. Bununla başarmaya çalıştığım şey, çalıştırdığım tüm koda tek bir yerde sahip olmaktır - hemen altında . Daha açıklayıcı bir ada sahip diğer tüm işlevler yeniden kullanılabilir.
Bu tekniğin dezavantajı, birçok işlevi tanımlamasıdır. Ancak korktuğum her yerde anonim işlevlerden kaçınmak için gerekli bir acı. Ve yine de risk nedir: yığın taşması mı? (şaka!)
Diğer yanıtlarda tanımlandığı gibi dizileri veya nesneleri kullanmak da işe yarayacaktır. Bu bir bakıma Kevin Reid tarafından önerilen cevaptır .
Ayrıca bind () veya Promise.all () kullanabilirsiniz. . Yine de kodunuzu bölmenizi gerektireceklerini unutmayın.
bağlama kullanarak
Eğer fonksiyonları yeniden kullanılabilir ama gerçekten içeride ne olduğunu tutmak gerekmez tutmak istiyorsanız o zaman çok kısa, kullanabileceğiniz bağlama () .
function tata( amazingData ) {
return afterSomething( amazingData )
.then( afterSomethingElse.bind(null, amazingData) );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
Basit tutmak için, bind () çağrıldığında işlevin başına argümanlar listesini (ilki hariç) ekler.
Promise.all kullanarak
Gönderinizde spread () kullanımından bahsettiniz . Kullandığınız çerçeveyi hiç kullanmadım, ama işte onu nasıl kullanabilmeniz gerektiği.
Bazıları Promise.all () 'ın tüm sorunların çözümü olduğuna inanıyor , bu yüzden sanırım bahsedilmeyi hak ediyor.
function tata( amazingData ) {
return Promise.all( [ amazingData, afterSomething( amazingData ) ] )
.then( afterSomethingElse );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( args ) {
var amazingData = args[0];
var processedData = args[1];
}
Verileri Promise.all () ' a aktarabilirsiniz - dizinin varlığına dikkat edin - söz verdiği sürece, ancak hiçbirinin başarısız olduğundan emin olun, aksi takdirde işlem duracaktır.
Ve args bağımsız değişkeninden yeni değişkenler tanımlamak yerine , harika işler için then () yerine spread () kullanabilmelisiniz .