我正在使用Angular HttpClient
将一些数据存储在服务器中,但我仍然坚持使用一条重复的指令。保存过程如下:
if(client is new){
//promise starts
store client and retrieve id
if(client has companion){
//promise starts
store companion and retrieve id
//promise starts
store product with previous retrieved id
}
//promise starts
store product with only client id
}else{
//promise starts
store product
}
正如您所看到的,“存储产品”指令重复三次,因为我需要在继续操作之前从服务器返回信息。 这是实际的代码:
//Check if the client is new
if (this.rent.client.id === 0) {
this.clientServce.saveClientToDatabase(this.rent.client)
.subscribe((results) => {
//Store the new client Id
this.rent.client.id = results.clientID;
//Check if companion exists and save it to database
if (this.rent.companion.id !== -1) {
this.clientServce.saveCompanionToDatabase(this.rent.companion)
.subscribe((companionResults) => {
this.rent.companion.id = companionResults.clientID;
//Save te rent
this.rentServices.saveRentToDatabase(this.rent).subscribe()
})
} else {
//Save te rent
this.rentServices.saveRentToDatabase(this.rent).subscribe();
}
})
} else {
//Save te rent
this.rentServices.saveRentToDatabase(this.rent).subscribe();
}
看起来确实可读。那么怎样才能以可读的方式管理客户端和同伴存储和存储产品呢?
答案 0 :(得分:1)
嵌套订阅块是一种反模式。因为您的代码容易受到多种竞争条件的影响。您正在操纵http调用之间的内部服务状态。这意味着,如果快速连续向import { mergeMap } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin';
const hasCompanion = this.rent.companion.id !== -1;
const rent = this.rent;
const saveClient$ = this.clientService.saveClientToDatabase(rent.client);
const saveCompanion$ = hasCompanion ? this.clientService.saveCompanionToDatabase(rent.companion) : of(null);
const saveRent$ = forkJoin([saveClient$, saveCompanion$]).pipe(mergeMap(([client, companion]: [any, any]) => {
return this.rentServices.saveRentToDatabase(companion ? {
...rent,
clientID: client.clientID,
companion: companion.companionID
} : {
...rent,
clientID: client.clientID,
})
}));
// single subscription and single manipulation of the internal state
saveRent$.subscribe(rent => this.rent = rent);
发出多个调用,其中一些调用可能最终会导致数据不正确。
尝试这样的事情:
<!DOCTYPE html>
<html>
<head>
<title>myFb</title>
<link rel="stylesheet" type="text/css" href="style1.css">
<script src="https://s3.amazonaws.com/stitch-sdks/js/library/v3/stable/stitch.min.js"></script>
<script src="assig02.js"></script>
</head>
<body onload="onLoadConnectDB()">
<p>Hello My App</p>
<div id="wlcom" align="center">
<button name="adding" onclick="addUser()">Add User</button><br>
<button name="deleting" onclick="deleteUser()">Delete User</button> <br>
<button name="logging" onclick="loginUser()">Login</button><br>
</div>
</body>
</html>