Oto, jak moim zdaniem powinieneś postępować.
rozszczepienie łańcucha
Ponieważ obie funkcje będą używać amazingData , warto mieć je w dedykowanej funkcji. Zwykle robię to za każdym razem, gdy chcę ponownie użyć niektórych danych, więc są one zawsze obecne jako argument funkcji.
Ponieważ twój przykład uruchamia jakiś kod, przypuszczam, że jest on w całości zadeklarowany wewnątrz funkcji. Nazwę to toto () . Wtedy będziemy mieli inną funkcję, która będzie działać zarówno afterSomething (), jak i afterSomethingElse () .
function toto() {
return somethingAsync()
.then( tata );
}
Zauważysz również, że dodałem oświadczenie o zwrocie , ponieważ zwykle jest to sposób na dotarcie do obietnic - zawsze zwracasz obietnicę, abyśmy mogli nadal łączyć ją w razie potrzeby. Tutaj cośAsync () wygeneruje amazingData i będzie dostępne wszędzie w nowej funkcji.
Od tego, jak będzie wyglądać ta nowa funkcja, zazwyczaj zależy, czy processAsync () jest również asynchroniczna ?
processAsync nie jest asynchroniczna
Nie ma powodu, aby zbytnio komplikować rzeczy, jeśli processAsync () nie jest asynchroniczna. Zrobiłoby to jakiś stary dobry kod sekwencyjny.
function tata( amazingData ) {
var processed = afterSomething( amazingData );
return afterSomethingElse( amazingData, processed );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
Zauważ, że nie ma znaczenia, czy afterSomethingElse () robi coś asynchronicznego, czy nie. Jeśli tak się stanie, obietnica zostanie zwrócona i łańcuch może być kontynuowany. Jeśli tak nie jest, zostanie zwrócona wartość wyniku. Ale ponieważ funkcja jest wywoływana z then () , wartość i tak zostanie opakowana w obietnicę (przynajmniej w surowym JavaScript).
processAsync asynchroniczny
Jeśli processAsync () jest asynchroniczna, kod będzie wyglądał nieco inaczej. Tutaj rozważymy, że afterSomething () i afterSomethingElse () nie zostaną ponownie użyte nigdzie indziej.
function tata( amazingData ) {
return afterSomething()
.then( afterSomethingElse );
function afterSomething( /* no args */ ) {
return processAsync( amazingData );
}
function afterSomethingElse( processedData ) {
}
}
To samo co poprzednio dla afterSomethingElse () . Może być asynchroniczny lub nie. Obietnica zostanie zwrócona lub wartość zawarta w rozwiązanej obietnicy.
Twój styl kodowania jest bardzo zbliżony do tego, czego używam, dlatego odpowiedziałem nawet po 2 latach. Nie jestem wielkim fanem posiadania wszędzie anonimowych funkcji. Trudno mi to czytać. Nawet jeśli jest to dość powszechne w społeczności. Dzieje się tak, gdy zamieniliśmy piekło zwrotne na czyściec obietnicy .
Chciałbym również, aby utrzymać nazwę funkcji w następnie krótki. I tak zostaną zdefiniowane tylko lokalnie. I przez większość czasu będą wywoływać inną funkcję zdefiniowaną w innym miejscu - tak wielokrotnego użytku - aby wykonać zadanie. Robię to nawet dla funkcji z tylko 1 parametrem, więc nie muszę pobierać i wychodzić funkcji, gdy dodaję / usuwam parametr do sygnatury funkcji.
Przykład jedzenia
Oto przykład:
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) {
}
Nie skupiaj się zbytnio na Promise.resolve () . To tylko szybki sposób na złożenie zdecydowanej obietnicy. Co staram się osiągnąć tego celu jest mieć cały kod używam w jednym miejscu - tuż pod thens . Wszystkie inne funkcje o bardziej opisowej nazwie są wielokrotnego użytku.
Wadą tej techniki jest to, że definiuje wiele funkcji. Ale obawiam się, że jest to ból konieczny, aby uniknąć wszędzie anonimowych funkcji. A jakie to ryzyko w ogóle: przepełnienie stosu? (żart!)
Używanie tablic lub obiektów zdefiniowanych w innych odpowiedziach również zadziałałoby. To w pewnym sensie odpowiedź zaproponowana przez Kevina Reida .
Możesz także użyć bind () lub Promise.all () . Pamiętaj, że nadal będą wymagać podzielenia kodu.
za pomocą bind
Jeśli chcesz, aby twoje funkcje były wielokrotnego użytku, ale tak naprawdę nie musisz przechowywać tego, co jest w środku, wtedy bardzo krótkie, możesz użyć bind () .
function tata( amazingData ) {
return afterSomething( amazingData )
.then( afterSomethingElse.bind(null, amazingData) );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
Aby było to proste, bind () doda listę argumentów (z wyjątkiem pierwszego) do funkcji, gdy zostanie ona wywołana.
przy użyciu Promise.all
W swoim poście wspomniałeś o użyciu funkcji spread () . Nigdy nie korzystałem z frameworka, którego używasz, ale oto jak powinieneś być w stanie go używać.
Niektórzy uważają, że Promise.all () jest rozwiązaniem wszystkich problemów, więc chyba zasługuje na wzmiankę.
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];
}
Możesz przekazać dane do Promise.all () - zwróć uwagę na obecność tablicy - tak długo, jak obietnice, ale upewnij się, że żadna z obietnic nie zawiedzie, w przeciwnym razie przestanie przetwarzać.
Zamiast definiować nowe zmienne z argumentu args , powinieneś móc używać funkcji spread () zamiast then () do wszelkiego rodzaju niesamowitych prac.