Pisze sobię własny crawler w nodeJS z użyciem puppeteera. Program mi się rozrósł i mam dosyć sporą ilość obietnic, przyjmijmy, że mam 200 różnych promisów robiących różne rzeczy. Połowa z nich jest returnowana przez funkcje z API puppeteera a połowa jest moich własnych.
Żeby ułożyć to w jakieś logiczne moduły aby całość była łatwa w utrzymaniu zacząłem zagnieżdżać promisy z użyciem syntaxu async/await.
Dla przykładu mam moduł, który crawluje aplikacje internetową i jest to 1 promise, w nim wywołuje 10 "child" promisów które wywołują 4-5 funkcji puppeteera, które również zwracają promise. Więc podsumowując ten 1 moduł ma pod sobą gdzieś z 50 obietnic i jest OK jakoś tam działa i robi co trzeba.
Problemy zaczynają się robić gdy chcę obsługiwać błędy z try/catch. Weźmy taki przykładowy kod
const grandchildPromise = () => {
return new Promise((resolve, reject) => {
throw 'some error msg';
//tutaj wywołanie jakiejś funkcji puppeteera
});
};
const childPromise = () => {
return new Promise(async(resolve, reject) => {
try {
await grandchildPromise();
} catch(e) {
console.log('caught in childPromise');
reject(e);
}
});
};
const parentPromise = () => {
return new Promise(async(resolve, reject) => {
try {
await childPromise();
} catch(e) {
console.log('caught in parentPromise');
reject(e);
}
});
}
parentPromise()
.then(() => {
console.log('fullfilled')
})
.catch(e => console.log(e));
Problemem jest, że przekazuje asynchroniczną funkcje jako executor do new Promise. Jest to anti-pattern i przez to nie wszystkie błędy z funkcji `granchildPromise` będą poprawnie złapane.
Jednak taka struktura zagnieżdżania mi najbardziej pasuje, próbowałem robić chainy z `then` i było to dla mnie dużo mniej wygodne więc nie bardzo chcę zmieniać samej architektury tego lecz muszę to zrefaktoryzować aby łapało mi wszystkie błędy a nie tylko część.
A więc moje pytanie - jak zrefaktoryzować ten kod aby zachować zagnieżdżone obietnice, zachować async/await lecz nie przekazywać async do new Promise żeby poprawnie łapało błędy?