Rxjs限制后增加循环计数器

时间:2017-08-23 20:41:13

标签: javascript angular rxjs

我有一个observable示例代码来打印一些值

 sample4Observable() {
    var observable = Observable.create(function (observer) {
      for (var i = 1; i <= 4; i++) {
        if (i <= 3) {
          observer.next(i);
        }
        if (i === 4) {
          setTimeout(() => {
            observer.next(i);
            observer.complete();
          }, 5000);
        }
      }
    });
    console.log('just before subscribe');
    observable.subscribe({
      next: x => console.log('got value ' + x),
      error: err => console.error('something wrong occurred: ' + err),
      complete: () => console.log('done'),
    });
    console.log('just after subscribe');
  }

输出

just before subscribe
got value 1
got value 2
got value 3
just after subscribe
got value 5
done

我的问题是,当值达到4时,我的循环结束。所以下一个值将是4而不是5.为什么RxJS跳过值4?

为了获得4的值,我可以改变我的代码,如下所示。但在上面的场景中,我有点困惑。任何人都可以解释

 setTimeout((i) => {
            observer.next(i);
            observer.complete();
          }, 5000,i);

2 个答案:

答案 0 :(得分:1)

设置超时时,内部函数将在经过一段时间后执行。当循环达到i === 4时,它开始超时,内部函数尚未执行。循环再向前递增i到5,然后循环终止,因为不再满足条件i <= 4。在经过5秒后(在i增加到5之后),超时完成并执行该功能。虽然启动超时时i === 4为真,但现在执行超时功能时,它是i === 5

这与RxJS没有直接关联。这个更简单的例子应该说明一下。只需在浏览器控制台中运行它:

let i = 0;
setTimeout(() => console.log(`the value of i is ${i}`), 500);
i++; 

答案 1 :(得分:1)

无论如何,它与RxJS没有任何关联,这就是javascript执行的发生。由于您在false之前循环播放,因此计数达到4,而i<=4一次i==4,您将使用setTimeout启动一个函数。因此,只要setTimeout注册,它就不会直接进行评估。 setTimeout是异步事件,浏览器将其置于名为Event Loop的内容中。等到javascript的所有同步执行都结束。由于for i++中的i值变为5。然后所有同步执行完成。 Javascript访问Event Loop来评估异步操作(它们也可以是事件)。那个时间setTimeout进行评估并等到5000(5秒),然后它会i值达到预期的5

即使您设置超时0而非5000,您也会得到相同的结果,即i = 5

由于javascript是单线程的,因此它总是评估同步代码,后跟异步代码。

在调用它时,您可以将i值作为参数传递给setTimeout函数。如果i值直接在函数范围内可用,那么就不会检查全局值。在这里查看MSDN Docs

setTimeout((i) => {
   observer.next(i);
   observer.complete();
}, 5000,i);