Наблюдаемый в угловых не работает параллельно - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть код, в котором я вызываю наблюдаемую функцию, используя подписку. Я ожидаю, что он будет работать параллельно, но он работает в последовательности.

makedownloadData () - это функция для хранения всех переменных переменной списка «showData» в другой переменной, скажем «downloadData». Функция занимает много времени для копирования всех переменных в downloadData и дальнейшей обработки. Поэтому я подумал о вызове этой функции с использованием метода наблюдаемой / подписки, чтобы она выполнялась параллельно, не вызывая задержки в текущей последовательности, но она работает только в последовательности. Без улучшения.

Первый метод (без наблюдаемого)

Вызов функции

this.downloadData=this.makeDownloadData() //This step is taking lot's of time as function respond late. 
console.log("print after function call")

Функция для вызова

public makeDownloadData() {
var main_data = this.showData;
var down_data:any = [];
for (var i=0; i<main_data.length; i++){
  var element: String = "";
  var newDate = new Date(main_data[i]["@timestamp"]);
  element = element.concat(this.convertDateToLocalFormat(newDate)+" ");
  element = element.concat(String(main_data[i]["cu_hostname"])+" ");
  element = element.concat(String(main_data[i]["log_agent"])+".");
  element = element.concat(String(main_data[i]["log_level"])+" ");
  element = element.concat(String(main_data[i]["app_name"])+": ");
  element = element.concat(String(main_data[i]["log_message"])+" ");
  down_data.push(element.concat("\n"));
}
return down_data;

}

Выход:

//Execution of function
"print after function call"

Второй метод (с наблюдаемым)

Импорт требований

import { Observable } from 'rxjs';
import 'rxjs/add/observable/of'

Вызов наблюдаемой функции.

this.makeDownloadData().subscribe(response => {
   console.log("Expected to print after") //This should be run in parallel and must printed after upcoming statement as this function is taking time to respond.
   console.log(response); //Expected to print after 
},
error => {
  console.log("Did not got response")
});

console.log("Expected to print before")

Функция для вызова

public makeDownloadData(): Observable<any> {
var main_data = this.showData;
var down_data:any = [];
for (var i=0; i<main_data.length; i++){
  var element: String = "";
  var newDate = new Date(main_data[i]["@timestamp"]);
  element = element.concat(this.convertDateToLocalFormat(newDate)+" ");
  element = element.concat(String(main_data[i]["cu_hostname"])+" ");
  element = element.concat(String(main_data[i]["log_agent"])+".");
  element = element.concat(String(main_data[i]["log_level"])+" ");
  element = element.concat(String(main_data[i]["app_name"])+": ");
  element = element.concat(String(main_data[i]["log_message"])+" ");
  down_data.push(element.concat("\n"));
}
return Observable.of(down_data)

}

Выход:

"Expected to print after"
Printing response
"Expected to print before"

Ожидаемый результат:

"Expected to print before"
"Expected to print after"
Printing response

Я хочу использовать observable для параллельного выполнения. Пожалуйста, помогите. если что-то неясно, чем я буду изменять вопрос, чтобы сделать его более ясным. Спасибо

Ответы [ 3 ]

0 голосов
/ 11 апреля 2019

Есть две проблемы:

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

Следующий код имеет полностью асинхронную наблюдаемую (благодаря параметру asyncScheduler функции of - без нее of является синхронной функцией, которая возвращает наблюдаемую):

const source = of('Hello, subscriber', asyncScheduler).pipe(
  tap(() => console.log('Inside observable')),
  map(x => {
    for(let i = 0; i < 1000000000; i++)
      for(let j = 0; j < 1; j++);

    return x;
  })
);
console.log('After observable')

source.subscribe(x => console.log(x));

Говоря, что это асинхронно, я имею в виду, что After observable будет в консоли немедленно. Через некоторое время вы увидите 'Inside observable', а затем 'Hello, subscriber'.

Если вы удалите asyncScheduler наблюдаемого, вы подождете некоторое время и увидите ту же самую последовательность ('After observable', 'Inside observable', 'Hello, subscriber'), но весь код будет заблокирован, пока цикл внутри наблюдаемого не закончится, и, сразу после этого вы увидите три строки, напечатанные на консоли почти одновременно . Посмотрите на эту демонстрацию: https://stackblitz.com/edit/rxjs-stackoverflow-556297976433166?file=index.ts

Так что вы можете попробовать это:

makeDownloadData(): any { // <== doesn't need to return an observable
  var main_data = this.showData;
  var down_data:any = [];
  for (var i=0; i<main_data.length; i++){
    var element: String = "";
    var newDate = new Date(main_data[i]["@timestamp"]);
    element = element.concat(this.convertDateToLocalFormat(newDate)+" ");
    element = element.concat(String(main_data[i]["cu_hostname"])+" ");
    element = element.concat(String(main_data[i]["log_agent"])+".");
    element = element.concat(String(main_data[i]["log_level"])+" ");
    element = element.concat(String(main_data[i]["app_name"])+": ");
    element = element.concat(String(main_data[i]["log_message"])+" ");
    down_data.push(element.concat("\n"));
  }
  return down_data // <== this doesn't need to return an observable
}

Обновление : я заменил of(this.makeDownloadData()) на of(1), иначе потребуется столько же времени для создания оператора, который был необходим для запуска функции в исходной задаче. Затем вы можете сопоставить его с желаемой функцией.

import { of, asyncScheduler } from 'rxjs'; 
import { map } from 'rxjs/operators';

...

this.downloadData=of(1, asyncScheduler)
    .pipe(map(() => this.makeDownloadData());

Использование of здесь не самый лучший подход для создания наблюдаемой, но, безусловно, он наиболее очевиден, поскольку мне нужен asyncScheduler, чтобы сделать его асинхронным. «1» в качестве первого параметра - тупые данные. Вы можете использовать что угодно. Функция of нуждается в параметре.

0 голосов
/ 11 апреля 2019

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

0 голосов
/ 11 апреля 2019

В отличие от обещаний, где код похож на

Promise.resolve("one").then(console.log);
console.log("two");

приводит к тому, что «два» печатаются перед «одним», наблюдаемые не являются асинхронными по природе, как обратные вызовы. Так что of("one").subscribe(console.log) будет печататься сразу, а не после окончания цикла события.

Вот более длинная лекция: https://www.syntaxsuccess.com/viewarticle/rxjs-subjects-emit-synchronous-values

...