问题
I have an API that might return []
result.
HTTP/1.1 200 OK
Date: Tue, 16 Apr 2018 06:06:22 GMT
Content-Type: application/json; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked
Request-Context: appId=cid-v1:...
[]
Here is my code that just does not work in that particular case:
getData(): Observable<Thing[]> {
return this.getData1()
.pipe(
flatMap(aData => {
const ids = aData.map(({ id }) => id);
const bData = this.getBData(ids); // emty result might be here
//test subscribe
this.getBData(ids).subscribe((data) => {
//just had that for a test, to confirm subsscribe never fires when response is `[]`
console.log(data);
});
return Observable.zip(
Observable.of(aData),
bData
);
}),
// map does not executing when api that getting called by `this.getBData(ids)` returns `[]`
map(([aData, bData]) => {
// Merge the results
const data: any = aData.concat(bData).reduce((acc, x) => {
acc[x.scriptNumber] = Object.assign(acc[x.scriptNumber] || {}, x);
return acc;
}, {});
return Object.values(data);
})
);
}
this.getBData(ids);
executing the http call and returns type of Observable<Thing[]>
:
getBData(ids):Observable<Thing[]> {
const filters = {
'id': [ids],
};
return this.http.post<Thing[]>('http://localhost:8080/api/thing', JSON.stringify(filters), {
headers: new HttpHeaders().set('Content-Type', 'application/json')
});
}
I have no errors on console.
What is the best practice to handle that scenario?
UPDATE:
I did change the api so now it is returns the data this way:
HTTP/1.1 200 OK
Date: Tue, 17 Apr 2018 09:36:11 GMT
Content-Type: application/json; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked
Request-Context: appId=cid-v1:...
{
data: [],
error: 'OK'
}
This way I always have the data in responce and my code works with a small modifications (aData.data
and bData.data
) however I still wonder why it didnt wrok in case of empty array, as @DanielWStrimpel commented it should emmit a value anyway...?
回答1:
First, there is a problem with your post
method (perceive empty array as no response body) or your API (return empty response body instead of empty array), either ways, now when you get empty data, it will just complete the request and return nothing.
Second, there is a workaround for this problem (while I prefer to add the status
field to the response body like you did), is to use RxJS toArray, like this:
this.getBData(ids)
.pipe(toArray())
.subscribe(([bData]) => {
// Process the data
});
Note: As you can see, toArray
emits an array of all items that the Observable emitted, that mean that in your case, if will return either an empty array or an array contains your data array [[item1, item2]]
.
来源:https://stackoverflow.com/questions/49868347/how-to-handle-an-empty-result-with-rxjs-observable