Как сохранить запрос в Angular? - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть эта функция для сохранения объектов в сервисе. В приложении angular.

save(object: Object): Observable<Book> {
  return this.http.put(this.baseUrl, object);
}

Поскольку все мы знаем, что http-запрос является асинхронным и может занять больше времени, чем мы ожидали.

При таких обстоятельствах, если я вызываю эту функцию save(object: Object) часто. Может случиться так, что последний запрос не будет выполнен, а следующий запрос уже отправлен. Это вызовет проблемы.

Объект, который я хочу сохранить, имеет некоторые уникальные ограничения, такие как name и optimisti c lock.

См. Некоторые случаи ниже: с obj1 и obj2

Случай 1: obj obj1 и obj2 имеют одинаковые имена, но разные идентификаторы;

obj1 {
  id: 1;
  name: 'name1';
  optimisticLock: 0;
}
obj2 {
  id: 2;
  name: 'name1';
  optimictic: 0;
}

В этом случае, если obj1 был отправлен по http, но еще не завершено, затем отправляется и obj2. Для obj2 серверная сторона проверит, дублировано ли имя. Хотя мы видим, что obj1 и obj2 имеют одно и то же имя, но поскольку этот obj1 еще не был сохранен, проверка имени obj2 пройдет. Поэтому проверка уникальности имени obj2 прошла, но сохранение все равно не удалось, и на стороне сервера возникнет исключение уникального ограничения.

Случай 2 Если obj1 и obj2 - это одни и те же данные, но с разными именами, например:

obj1 {
  id: 0;
  name: 'previousName';
  optimisticLock: 0;
}
obj2 {
  id: 0;
  name: 'newName';
  optimisticLock: 0;
}

Сначала отправьте obj1, а затем отправьте obj2 для сохранения , obj1 сохранено и возвращаемое значение на стороне сервера выглядит следующим образом

obj1 {
  id: 0;
  name: 'previousName';
  optimisticLock: 1;
}

Это обновит его оптимизм c lock 0 -> 1; Но этот ответ еще не был возвращен клиенту, поэтому obj2 optimisticLock по-прежнему равен 0 и отправляется на сторону сервера. Очевидно, что запрос на сохранение obj2 не будет выполнен.

Мы ожидали сохранить последнее изменение, но мы сохранили только obj1. Так что это серьезная проблема.

У меня есть идея решить эти два случая. Если я использую очередь, чтобы поставить все запросы. Все запросы должны быть помещены в эту очередь, и эта очередь отправляет первый запрос, прежде чем получить ответ от первого запроса, никакой другой запрос не будет отправлен. После ответа на первый запрос обновите эту очередь в соответствии с ответом. Затем отправьте второй запрос.

Но я не знаю, как закодировать это решение, кто-нибудь знает, как это сделать? Или у вас есть лучшее решение для решения проблем в case1 и case2?

1 Ответ

0 голосов
/ 24 апреля 2020

Вы можете использовать rx js, чтобы решить эту проблему. Вы должны предоставить триггер на основе субъекта, который затем вызывает метод сохранения.

Пример:

@Injectable()
export class MyService {

  constructor(private httpClient: HttpClient) {}

  save(object: Object): Observable<any> {
    return this.httpClient.put('some-url', object);
  }

}

@Component({})
export class MyComponent implements OnInit {
  save$: Subject<Object> = new Subject();

  constructor(private service: MyService) {}

  ngOnInit() {
    this.save$.pipe(concatMap(o => this.service.save(o)))
  }

  save(object: Object) {
    this.save$.next(object);
  }

}

Существует несколько операторов rxjs / для обработки входящих событий.

  • concatMap обрабатывает входящие события последовательно. В вашем случае он ждет, пока ваш http-запрос не будет завершен, а затем выполняет следующий. Таким образом, ваша очередь

  • switchMap не подсчитывается из внутренней наблюдаемой и обрабатывает следующее событие. Это означает, что текущий httpCall будет отменен, а следующий будет выполнен. В конце концов, последнее сохранение будет выигрывать

  • mergeMap каждый раз, когда происходит событие, создается новая внутренняя наблюдаемая и подписывается. Это означает, что все ваши запросы будут выполнены независимо от того, был ли завершен предыдущий или нет.

  • выхлопная карта Это оператор не прерывайте меня. Когда внутренняя наблюдаемая не завершена, она игнорирует все входящие новые события.

Внутренняя наблюдаемая - это в основном ваш httpCall, а внешняя наблюдаемая - ваш субъект. В этом примере я использовал concatMap, который будет обрабатывать все входящие действия сохранения последовательно, как очередь.

...