Как справиться с обещанием внутри водопроводной карты - PullRequest
0 голосов
/ 06 декабря 2018

Я определенно уверен, что запутался здесь, поэтому, пожалуйста, любая помощь приветствуется.

Вот мой сценарий:

Я извлекаю из Firestore документ:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
      map( document => {

      })
    );

Здесь все в порядке.

Но внутри карты мне нужно решить (или нет) обещание

Например:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
      map( document => {
        // This is a promise the below part 
        const data = await EventImporterJSON.getFromJSON(document.payload.data())
        return data
      })
    );

Я понимаю, что await там не может произойти.Я очень запутался, как решить эту проблему, возможно, я недостаточно долго работал с observables и rxjs.

В конце концов я пытаюсь добиться:

Получить документ.Составьте карту и обработайте ее, но внутри процесса мне нужно выполнить обещание.

Я не хочу возвращать это обещание звонящему.

Имеет ли это смысл?

Или я это неправильно структурировал?

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Это типичный вариант использования для mergeMap или concatMap:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
  mergeMap(document => {
    // This is a promise the below part 
    return EventImporterJSON.getFromJSON(document.payload.data())
  })
);

Однако вы также можете использовать async - await, поскольку такие операторы, как mergeMap обрабатывают Observables, Promises,массивы, ... таким же образом, так что вы можете просто вернуть Promise в функции проекта mergeMap s, и она будет работать нормально.

Как правило, вам не нужно использовать несколько await в одном методе, потому что более "Rx" способ выполнения операций - это цепочка операторов, но если вы хотите, вы можете, потому что async метод возвращает Promiseи RxJS будет обрабатывать его как любое другое Обещание.

const delayedPromise = () => new Promise(resolve => {
  setTimeout(() => resolve(), 1000);
})

of('a').pipe(
  mergeMap(async v => {
    console.log(1);
    await delayedPromise();
    console.log(2);
    await delayedPromise();
    console.log(3);
    await delayedPromise();
    return v
  })
).subscribe(console.log);

Демонстрация в реальном времени: https://stackblitz.com/edit/rxjs-3fujcs

0 голосов
/ 06 декабря 2018

Наблюдаемые можно рассматривать как слой до обещаний, почему бы вам не использовать свое обещание таким образом?как это:

let getDataFromJson(payloadData){
    return from(EventImporterJSON.getFromJSON(payloadData());
}

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
  map(document=>document.payload.data),
  switchMap( payloadData=> getDataFromJson(payloadData)))
.subscribe(result=>{
    //final result
});

1 направляет вашу первую наблюдаемую с картой только для того, чтобы упростить ваше возвращающее значение

2 switchMap к другой наблюдаемой, которая будет вашим обещанием в качестве наблюдаемой (с "from"operator);

Оператор отображения сделан для улучшения результата синхронно и «чисто», например, возвращает только несколько свойств объекта или фильтрует данные, здесь вы хотите связать две асинхронные операции, поэтому я предлагаю вамдержать его в подходе RX

...