我正在使用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 {}
第一个按预期打印出来,而当我在循环外读取它时,对象发生了一些奇怪的事情。 有人可以帮我理解发生了什么。
答案 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));
之前打印。因此,当您订阅时,如果您想对价值变化做任何事情,请将整个内容放入订阅中。