Node.js / Nest JS: принудительный HTTP-вызов на go (что делает его более заметным) - PullRequest
1 голос
/ 23 апреля 2020

Я разрабатываю библиотеку для некоторых конечных пользователей, с вызовами API через HttpService, результат которого будет использовать конечный пользователь или нет .

        end-user consumer <==> my library <=(HTTP)=> remote API

Теперь HttpService использует cold Observables , что означает, что он вызовет HTTP-вызов only , если мы подпишемся на сгенерированную Observable. Если я верну это Observable моему конечному пользователю, и он не подпишется на него, потому что в своем конкретном сценарии использования им не нужен результат, API никогда не будет вызываться.

По этой причине я склонны подписаться на Observable, прежде чем возвращать его конечному пользователю, но я не совсем уверен, что это элегантное или безопасное решение, отсюда и этот пост. Мой код выглядит так (упрощенно для поста и с использованием HttpService из @ nestjs / common):

ServiceToAccessAPIData.ts

export class ServiceToAccessAPIData {
  ...
  callToEndPoint(): Observable<any> {
    const obs = httpService.get(someUrl)
    .pipe(
      shareReplay(1) // see A
    );

    obs.subscribe(()=>{},()=>{}); // see B

    return obs;
  }
  ...
}

С:

  • A : поскольку я хочу, чтобы каждая подписка не отправляла HTTP-вызов, мне нужно делиться результатами вызова между подписчиками; и поскольку я подписываюсь сейчас (в B), и конечный пользователь может подписаться позже (даже после того, как API отправил результат), и они, очевидно, не должны пропустить результат, я использую оператор shareReplay (1), который хранит последний результат и передает его всем новым подписчикам.
  • B : я подписываюсь сейчас, чтобы немедленно принудительно вызвать HTTP-вызов на go. Мы обеспечиваем успех, но особенно метод обработки ошибок , потому что необработанное Исключение взрывает Node.js сервер).

Теперь, это кажется немного сложным для такого тривиального варианта использования : 'предоставляет конечному пользователю безопасный способ совершения вызова независимо от того, использует он результат или нет' .

Существует ли лучший, более простой и элегантный способ сделать это?

Кроме того, с точки зрения производительности, будет ли какой-либо результат с этой техникой?

Наблюдатели HttpService генерируют только один раз, а затем завершают, поэтому подписки будут автоматически отписался. Но мне интересно, что станет с базовым Observer, наблюдаемым shareReplay. Я полагаю, что это будет сборщик мусора, когда в Observable, который я возвращаю, больше не будет ссылок на него, но мне интересно.


Использование обещаний (как предложено MoazzamArif)

Вышеприведенные вопросы вполне остаются (особенно если нужно придерживаться Observables), но решением исходной проблемы могло бы быть использование .toPromise () в качестве возвращаемого значения до конца. user.

return obs.toPromise();

.toPromise () подписывает на Observable (он немедленно выполняет HTTP-вызов) и переносит его в Promise, что разрешит до последнего переданного значения Observable после завершения Observable (в случае HttpService, как только API вернул результат).

=> Это фактически отвечает на необходимость 'обеспечить безопасный способ для конечного пользователя, чтобы сделать вызов, используют ли они результат или нет '.

Теперь давайте копать дальше. Я полагаю, это exoti c и странно сценарий, чтобы рассмотреть, но как могли бы мы справиться с такой ситуацией:

  • при HTTP-вызове возникает ошибка
  • , цепочки конечного пользователя .then () и .catch (), но только после произошла ошибка

=>, поскольку .toPromise () напрямую подписывается на Observable, но обработчик ошибок не предоставлен, ошибка всплывет и произойдет sh приложение

=> если мы напрямую подключим .catch(err => anyValue) к возвращенному обещанию, ошибка будет обнаружена, но конечный пользователь получит anyValue в .then () , и не сможет обработать исходную ошибку

=>, если мы напрямую подключим .catch(err => { someHandling(); return Promise.reject(err); } к возвращенному обещанию, потому что пользователь не связал свои .catch () пока не появится новая ошибка из-за отклоненного обещания, и sh приложение

Следовательно, я полагаю, что решения не существует, и описанный выше сценарий просто невозможно обработать (можно было обработать его с помощью решения Observable .shareReplay (1)).

...