角度可观察到不是平行工作

时间:2019-04-11 09:27:43

标签: angular rxjs observable angular2-observables

我有一个代码,其中我使用订阅调用了一个可观察的函数。 我希望它可以并行运行,但可以按顺序运行。

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 :(得分:0)

与承诺不同,代码类似

Validators.requiredTrue instead of Validators.required

导致在“一个”之前打印“两个”,因此可观察的对象本质上不是异步的,就像没有回调一样。因此Promise.resolve("one").then(console.log); console.log("two"); 会立即打印,而不是在事件循环刻度结束之后。

这是更长的一次演讲: https://www.syntaxsuccess.com/viewarticle/rxjs-subjects-emit-synchronous-values

答案 1 :(得分:0)

有两个问题:

  1. 您的函数makeDownloadData()不是可观察的,它只是返回一个可观察的(花费时间的代码在return语句之前)
  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函数需要一个参数。

答案 2 :(得分:0)

首先,您需要在订阅获取数据后调用打印前的订阅方法,然后调用打印后的普通方法,以便现在您可以获取正确的答案,这将有助于您进行任何澄清,请依靠这个答案