Понимание результатов Promise vs Obervables - PullRequest
2 голосов
/ 14 января 2020

Обещание:

Реализация

  getDataPromise(): any {
    let promise = new Promise((resolve, reject) => {
      resolve([
        { brand: 'iPhone', model: 'Xmax', price: '$1000' },
        { brand: 'Samsung', model: 'S10', price: '$850' }
      ]);
    });
    return promise;
  }

// promise call
getDataPromise.then((data) => { 
    console.log("Result: ", data);
});

Результат является массивом:

Result: [
  { brand: 'iPhone', model: 'Xmax', price: '$1000' },
  { brand: 'Samsung', model: 'S10', price: '$850' }
]

Наблюдаемый

Реализация

  import { from } from 'rxjs';

  getDataObservable(): any {
    return from([
      { brand: 'iPhone', model: 'Xmax', price: '$1000' },
      { brand: 'Samsung', model: 'S10', price: '$850' }
    ]);
  }

// observable call
getDataObservable().subscribe((data) => {
    console.log("Result: ", data);
});

Результат - это 2 объекта в последовательности:

Result: { brand: 'iPhone', model: 'Xmax', price: '$1000' }
Result: { brand: 'Samsung', model: 'S10', price: '$850' }

Пытался понять разницу, пошел через онлайн-материалы, но до сих пор не может ответить на следующие 2 вопроса.

  • Почему результат отличается?

  • Как получить результат из наблюдаемый в виде массива (как в обещании)?

Ответы [ 3 ]

4 голосов
/ 14 января 2020

Обещание заканчивается - оно разрешается (then) или отклоняет (catch) и все. Наблюдаемые потоки значений до его окончания (много раз, он никогда не заканчивается, вы просто «теряете интерес» или отписываетесь от потока значений).

Мне нравится пример нажатия клавиши - если вы используете обещание для разрешить / отклонить на основе события нажатия клавиши, вы будете когда-либо слушать только «следующее» нажатие клавиши, а затем вам нужно будет создать новое обещание для прослушивания следующего и т. д.

С Наблюдаемые, вам нужно всего лишь создать его, и он будет просто непрерывно передавать вам значения, пока вы не перестанете интересоваться (отписаться).

Promise:

const subscribeToKeyPress = () => {
  let resolve;
  document.addEventListener('keydown',function listener(e) {
      resolve(e);
      // unsubscribe from the event listener, otherwise you've got a memory leak
      document.removeEventListener('keydown',listener);
  });
  return new Promise(r => resolve = r);
}

subscribeToKeyPress().then(e => {
  // done, never to receive another result
});

#####
Observable:

const subscribeToKeyPress$ = () => fromEvent(document,'keypress);

const unsubscribe = subscribeToKeyPress$().subscribe(e => {
  // called continually on each keypress until you unsubscribe
});

unsubscribe(); // your callback function won't be called anymore, if you don't call unsubscribe when you're done, you've got a memory leak

#####
Callback Function - the simplest "observable"

const subscribeToKeyPress = callback => {
   const fn = e => callback(e); // this function will get called over and over until you unsubscribe
   document.addEventListener('keypress',fn);
   return () => document.removeEventListener('keypress',fn);
}

const unsubscribe = subscribeToKeyPress(e => {
  // called continually on each keypress until you unsubscribe
});

unsubscribe(); // your callback function won't be called anymore, if you don't call unsubscribe when you're done, you've got a memory leak

Как получить результат из наблюдаемого как массив (аналогично обещанию)?

Проверить https://www.learnrxjs.io/operators/utility/topromise.html

Также имеет отношение к toPromise: https://github.com/ReactiveX/rxjs/issues/2536

Если ваша наблюдаемая не «завершается» (как слушатель нажатия клавиш), toPromise никогда не сработает (если вы сначала не pipe(take(1)), но это много для новичка ie, без обид, но из мира обещаний, наблюдаемые действительно трудно rok - из моего личного опыта - пока их больше нет).

3 голосов
/ 14 января 2020

Обещания и наблюдаемые являются асинхронными. В любом случае вам нужно будет обрабатывать их соответственно

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

Как Как указано в документации, оператор from

Превратит массив, обещание или итерацию в наблюдаемую.

Именно поэтому getDataObservable печатает массив объекты как разные последовательности.

Если вы хотите sh вернуть их как одну последовательность, вместо этого используйте оператор из .

Emit variable amount значений в последовательности, а затем выдает полное уведомление.

import { of } from 'rxjs';

const getDataObservable = () => {
  return of([
    { brand: 'iPhone', model: 'Xmax', price: '$1000' },
    { brand: 'Samsung', model: 'S10', price: '$850' }
  ]);
}

getDataObservable().subscribe((data) => {
    console.log("Result: ", data);
});

Вот демо .

1 голос
/ 14 января 2020

Это просто потому, что для from:

Для массивов и итераций все содержащиеся в них значения будут выводиться в виде последовательности!

, поэтому, если вы сделаете это :

from([[
  { brand: 'iPhone', model: 'Xmax', price: '$1000' },
  { brand: 'Samsung', model: 'S10', price: '$850' }
]]);

тогда это будет тот же результат.

Разница между наблюдаемым и обещанием:

Но есть одно существенное различие между наблюдаемым и обещанием:

  1. если вы зарегистрируете наблюдаемое после события, ничего не произойдет с событием, которое уже произошло (только получит уведомление о будущих событиях). Для обещания then() все равно вступит в силу.
  2. для наблюдаемых, вы можете продолжать получать уведомления о событиях того же типа. Для обещания, когда оно выполнено (разрешено или отклонено), оно выполняется только один раз.
...