Angular 2 typescript变量值随范围而变化

时间:2017-08-23 09:14:21

标签: javascript angular loops object typescript

我正在使用Angular 2创建一个webapp并遇到一个值得理解的奇怪问题。

我正在尝试在分配新值之后立即打印对象的值。以下是代码:

do {
    this._sharedService.readServerStatus().subscribe(res =>
      {
        this.surveyStatus = JSON.parse(JSON.stringify(res));
        console.log(this.surveyStatus);
    });
    console.log("ne");
    console.log(this.surveyStatus);
  }
  while(this.surveyStatus.isBusy());

在此代码中,surveyStatus是我希望打印到控制台的对象。以下是浏览器控制台的输出:

Object {serverBusy: 1, terminate: 0}
ServerStatus {}

第一个按预期打印出来,而当我在循环外读取它时,对象发生了一些奇怪的事情。 有人可以帮我理解发生了什么。

2 个答案:

答案 0 :(得分:1)

问题是您的readServerStatus()调用是异步的,因此会在值发出值时打印该值。但是你的其余代码不会等待它,所以你的第二个console.log会打印一个空对象。

但是你的代码存在很大的问题,你在while循环中产生了大量的订阅而没有完成它们,这将导致内存泄漏。

我建议将repeatWhile运算符与takeUntil RxJ用于此类任务。

以下是一个例子:

let mockResponse = { serverBusy: 1, terminate: 0 };
const request = () => {
  return Rx.Observable.of(mockResponse).delay(500); // emulate api call
};

request()
  // repeat the request while isBusy is true
  .repeatWhen(notifications => {
    return notifications.takeWhile(() => {
      return !!mockResponse.serverBusy;
    });
  })
  .subscribe(res => {
    console.log(res);
  });

setTimeout(() => {
   mockResponse.serverBusy = 0;
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.3/Rx.min.js"></script>

这是另一个使用switchMap从响应中读取数据并确定是否需要重试的示例,如果不是,则发出响应。

let mockResponse = { serverBusy: 1, terminate: 0 };
const apiCall = () => {
  return Rx.Observable.of(mockResponse).delay(500); // emulate api call
}

function makeRequest$() {
  let request$ = apiCall()
    .switchMap(res => {
      console.log('is busy:', !!res.serverBusy);
      return !!res.serverBusy ? request$ : Rx.Observable.of(res);
    });
  return request$;
}

makeRequest$().subscribe(res => {
  console.log(res);
});

setTimeout(() => {
   mockResponse.serverBusy = 0;
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.3/Rx.min.js"></script>

答案 1 :(得分:0)

它正在发生,因为订阅之外的控制台打印不会等待新的值赋值。它将在新值到达并作出this.surveyStatus = JSON.parse(JSON.stringify(res));之前打印。因此,当您订阅时,如果您想对价值变化做任何事情,请将整个内容放入订阅中。