#angular #angular-ngrx-data #ngrx-data
#angular #angular-ngrx-data #ngrx-data
Вопрос:
Я обновляю множество записей в разделе @ngrx /data, который вызывает удаленный API в фоновом режиме для синхронизации базы данных и локального хранилища.
dataList.forEach((entity) => {
const p = this.entitySvc
.getEntityCollectionService(storeName)
.upsert(entity)
.toPromise();
promises.push(p);
});
return Promise.all(promises);
Проблема, с которой я сталкиваюсь, заключается в том, что удаленный вызов API происходит за пределами моего кода, и это происходит так быстро, что соединения перегружают браузер:
net::ERR_INSUFFICIENT_RESOURCES
Регулирование приведенного выше кода не помогает, потому что удаленные вызовы API происходят вне моего контроля.
Есть ли способ ограничить вызовы удаленного API ngrx / data или другой способ решения этой проблемы?
Ответ №1:
Я бы использовал оператор mergeMap rxjs, чтобы добавить параллелизм между запросами сервера:
updateEntities(): Observable<any> {
return from(dataList).pipe(
mergeMap(entity => this.entitySvc
.getEntityCollectionService(storeName)
.upsert(entity), 2)
);
}
Затем при необходимости вызывайте функцию:
this.updateEntities().subscribe();
Обратите внимание, что значение параллельного параметра mergeMap равно 2, что означает, что параллельно будут отправляться только 2 запроса, предотвращая одновременное обращение к серверу одновременно. Вы можете настроить это число по своему усмотрению.
PS: Имейте в виду, что при вызове функции toPromise() для наблюдаемого объекта она будет выполнена немедленно.
Ответ №2:
Вариант 1
Приведенный ниже подход с использованием Observable
без необходимости сначала конвертировать в promise должен снизить использование ресурсов, попробуйте
import { forkJoin } from 'rxjs'
...
myFunction() {
return forkJoin(dataList.map(entity => this.entitySvc
.getEntityCollectionService(storeName)
.upsert(entity)))
}
ПРИМЕЧАНИЕ: мы возвращаем an Observable
, поэтому там, где вы изначально вызывали это Promise
, нужно будет изменить с a .then()
на a subscribe()
myFunction().subscribe()
Вариант 2
Если вышеуказанное не решает, попробуйте ниже. Подход связывает Observable
и обрабатывает следующий запрос только после завершения предыдущего запроса.
ПРИМЕЧАНИЕ: это может быть медленнее, и вам может потребоваться указать пользователю ход выполнения операции
this.dataList
.pipe(
tap(() => 0),
tap(({ length }) => (this.totalItems = length)),
flatMap(item => item)
)
.pipe(
concatMap(entity =>
this.entitySvc.getEntityCollectionService(storeName).upsert(entity)
)
)
.pipe(tap(() => (this.progress = 1)))
.subscribe({
next: console.log
});