以角度一个接一个地运行可观察的

时间:2017-10-30 11:39:59

标签: javascript angular rxjs

我有以下数据的对象数组:

 [  
   {  
      "name":"Uber",
      "points":20,   
      "nodeName":"C=GB,L=London,O=Uber",
      "port":10007,
      "nodeType":"merchant"
   },
   {  
      "name":"Starbucks",
      "points":20, 
      "nodeName":"C=US,L=New York,O=Starbucks",
      "port":10010,
      "nodeType":"merchant"
   },
   {  
      "name":"KFC",
      "points":20, 
      "nodeName":"C=US,L=New York,O=KFC",
      "port":10013,
      "nodeType":"merchant"
   }
]

我想循环遍历此数组并使用动画显示determinate progress栏,并且还应该看到下面image.for points属性中显示的点数增加,并且想要一个接一个地显示它。即首先显示的优步进度条将为优步点加载至100%。对于星巴克,然后是肯德基。

enter image description here

我试过下面的代码,其中res是我上面的数组:

 res.forEach((v, i) => {
        Observable.timer(100).subscribe((i) => {
            let interval = Observable.interval(100).subscribe((i) => {
                this.percentageCom = (this.points / this.PointsAdded) * 100;
                if (this.percentageCom === 100) {
                    // this.isHidden = true;
                    interval.unsubscribe();
                }
            })
        });
    });
    let timer = Observable.interval(100).subscribe(() => {
        this.points++;
        if (this.points === 60) {
            timer.unsubscribe();
            // this.router.navigate(['/main/dashboard']);
        }
    });

和HTML:

<div class="vendor">{{merchantName|| 'Uber'}}</div>
<mat-progress-bar mode="determinate" value="{{percentageCom }}"></mat-progress-bar>

但是上面的代码不是一个接一个地显示我的进度条,因为那些东西是异步的,显示了一些奇怪的输出,即同时显示进度条。 有没有办法为数组的每个元素一个接一个地显示上面的加载器?

已更新

我的使用案例如下:

  • 从服务响应我得到上面提到的对象数组
  • 让我们考虑该对象数组的第一项。它有点20;所以在我的视图中,积分应该从0增加到20(就像计数器一样)
  • 因此,虽然这一点增量发生到20,但我希望在这种情况下显示Uber的百分比进度条,它将完全100%运行。
  • 对于一个对象,一旦超过2点完成,即对象数组中的下一个项目应该发生同样的情况。

以上是我想要实施的步骤。但由于intervaltimer是异步的,我无法通过循环abpve对象来一个接一个地运行它。

我在计时器和间隔中弄乱了代码......不知何故,我无法通过它!

3 个答案:

答案 0 :(得分:3)

我并没有找到嘲笑加载行为的目的,但我认为你正在寻找类似于此代码剪切的东西。我也想,并且示例显示,您可以删除点变量..但我不确定,因为我不了解100%的上下文。

const res =  [  
   {  
      "name":"Uber",
      "points":20,   
      "nodeName":"C=GB,L=London,O=Uber",
      "port":10007,
      "nodeType":"merchant"
   },
   {  
      "name":"Starbucks",
      "points":20, 
      "nodeName":"C=US,L=New York,O=Starbucks",
      "port":10010,
      "nodeType":"merchant"
   },
   {  
      "name":"KFC",
      "points":20, 
      "nodeName":"C=US,L=New York,O=KFC",
      "port":10013,
      "nodeType":"merchant"
   }
];

Rx.Observable.from(res)
.map( (value) => {
    return Rx.Observable.interval(100)
          .scan((acc, curr) => acc + 1)
          .take(value.points+1)
          .map(currentPoints => {
              const percentage = (currentPoints / value.points) * 100;
              return {arrayItem: value, percentage: percentage}
          })
})
 .concatAll()
 .subscribe((data) => {
    console.log(data.arrayItem.name + ': ' + data.percentage);
 });
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.8/dist/global/Rx.umd.js"></script>

编辑:我编辑了解决方案,现在是系列。

解释

  • 首先,我们将数组转换为流。 'Observable.from(RES)。
  • 对于数组中的每个项目,现在在流中,我们将其映射到Observable.interval(100)
  • 我们采用Observable间隔,我们计算它通过扫描发出的时间,我们只完成它作为数组项目点的项目​​。
  • 之后我们将值与当前百分比进行映射。
  • concatAll()运算符只是连接我们的可观察序列。
  • 最后,subscribe方法只显示结果的控制台日志

答案 1 :(得分:0)

我不确定,但我认为你在错误的地方做了一段时间。您应该在http get上执行此操作,然后您的订阅者将捕获具有间隔的可观察对象的更改。您正在寻找的内容可能称为投票请求,此处是高频率

helpful articlerelated issue

示例component.ts文件:

import { Component, OnInit } from '@angular/core';
import { Service } from './service';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css']
})

export class MainComponent implements OnInit {

  constructor(private service: Service) { }

  ngOnInit() {

   this.service.getNewValue()
     .subscribe((res) => console.log(res));

  }

}

示例service.ts文件:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs'; // ! Dont forget to Import Observable !

@Injectable()

export class Service {

  constructor(private http: Http) { }

  getNewValue = () => {
    return Observable 
      .interval(1000)
      .flatMap((i) => this.http.get("http://yourhost.com/api"))
  }

}

没有测试它,但应该解决你的问题

答案 2 :(得分:0)

您正在为每个项目创建一个新计时器。我不认为这就是你想要的。

我想你想要这样的东西:

{{1}}

此外,这可能会如此快速地处理,你不会看到它。