Проблема: мне нужно скачать огромный файл (5-10 ГБ) с простыми XHR-запросами, чтобы упростить вопрос, мне нужно сделать как минимум: 100 запросов (может быть больше).
Я хотел бы улучшить производительность с помощью RXJS (параллельные http-запросы).
Вопросы:
- Можно ли вообще улучшить производительность с помощью Parallel?
- Разве распараллеливание запросов не будет таким же, как использование 1 запроса для каждой итерации цикла запроса? Пропускная способность одинакова - НЕТ?
- Есть ли другие способы улучшить мой перф?
Stack:
- Угловой 7,2.х
- Машинопись 3.2.4
- Rxjs 6.4.0
Чего я на самом деле достиг:
Что мне действительно нужно, так это применить синхронизацию к mergeMap
, чтобы включить или выключить ее, например, у меня есть 100urls, но я не хочу, чтобы они запускались до последнего из них.
Например, я хочу, чтобы он работал до 17-го числа, но приостановит выполнение запросов и будет ждать завершения определенной логики и запроса.
Пример кода:
from(observableQueries)
.pipe(
mergeMap(partialQuery => this.messageService.getResults(partialQuery, true), 4),
takeWhile(o => {
if (!o.isMoreResults && o.auditMessageList.length === 0) {
this.logger.log(`First page that returns false ${ o.number }`);
this.logger.log(`Count of responses that exists in array: ${ allResults.length }`);
if (!firstPageThatShouldBeStopped) {
firstPageThatShouldBeStopped = o.number;
}
if (allResults.length === firstPageThatShouldBeStopped) {
return false;
}
}
return true;
}),
retryWhen(genericRetryStrategy()),
catchError((err, caught) => {
this._alertService.error(this._translate.instant('EXPORT_TO_CSV_DOWNLOAD_ERROR'));
return throwError(err);
})
)
.subscribe(
(res: MessagesResult) => {
if (reThrowError) {
this.logger.info('Error will be thrown for e2e purposes');
throw new Error('Error will throw for e2e purposes');
}
if (res.isMoreResults && res.auditMessageList.length > 0) {
allResults[res.number] = res;
this.subject.next(true);
} else if (!res.isMoreResults && res.auditMessageList.length > 0) {
allResults[res.number] = res;
this.subject.next(true);
} else {
this.subject.next(false);
}
},
err => {
// clear subject after emitting value...
this.subject.next(true);
return this.handleError(err);
},
() => {
this.logger.info('Download file finished...');
this.logger.info('Time consumed: ', performance.now() - start);
try {
this.logger.info(`Count Responses: ${ allResults.length } `);
const allResultSorted = this._sortResults(allResults);
let counter = 0;
for (let i = 0; i < allResultSorted.length; i++) {
this.logger.info('Index: ' + i, allResultSorted[i]);
counter += allResultSorted[i].auditMessageList.length;
this.logger.info('Length OF Messages: ' + i, counter);
this.fileSaver.save(!allResultSorted[i].isMoreResults, allResultSorted[i].auditMessageList,
`audit-events_${ LOCAL_QUERY_COPY.application }_${ timestamp }_${ moment()
.tz(this._timezoneService.timezone).zoneName() }.csv`, null, headers);
}
this.subject.next(false);
} catch (e) {
this._alertService.error(this._translate.instant('EXPORT_TO_CSV_DOWNLOAD_ERROR'));
return this.handleError(e);
} finally {
// clear subject after emitting value...
this.subject.next(true);
}
}
);
Код работает! Но проблема в избыточных вызовах. Как можно заставить их остановиться, пока не будут выполнены последние запросы.