Есть две проблемы:
- ваша функция
makeDownloadData()
не является наблюдаемой, она просто возвращает одну наблюдаемую (код, который требует времени перед оператором возврата)
- не все наблюдаемые являются асинхронными по умолчанию (на самом деле, только некоторые из них действительно асинхронны по умолчанию)
Следующий код имеет полностью асинхронную наблюдаемую (благодаря параметру 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
нуждается в параметре.