Angular HttpClient获取服务返回得太早

Angular HttpClient获取服务返回得太早,angular,ionic3,rxjs,angular-httpclient,Angular,Ionic3,Rxjs,Angular Httpclient,我正在尝试将旧的Http代码转换为新的Httpclient格式,但Get服务过早地将控制权返回给调用函数,因此它无法获取返回的数据 我尝试过使用async/await,但它对控制流没有影响 我对可观测事物还不熟悉,所以我肯定这是我做得不对的事情,但我不知道是什么 这些是我的代码中的函数,使用Httpclient的subscribe功能,具有getAsJson函数的新格式。我只想从http调用返回数据,所以我没有在options参数中包含“observe:‘response’” loadLoyal

我正在尝试将旧的Http代码转换为新的Httpclient格式,但Get服务过早地将控制权返回给调用函数,因此它无法获取返回的数据

我尝试过使用async/await,但它对控制流没有影响

我对可观测事物还不熟悉,所以我肯定这是我做得不对的事情,但我不知道是什么

这些是我的代码中的函数,使用Httpclient的subscribe功能,具有getAsJson函数的新格式。我只想从http调用返回数据,所以我没有在options参数中包含“observe:‘response’”

loadLoyaltyDetails调用getLoyaltyDetails,它执行一些与此处所示不同的操作,然后调用getAsJson

职能:

loadLoyaltyDetails():承诺{
返回此.loyalty.getLoyaltyDetails()。然后(数据=>{
console.log(“在loadLoyaltyDetails中,data=,data”);
})
.catch(this.handleServiceLoadingError.bind(this))
}
getLoyaltyDetails():承诺{
返回这个.callApi.getAsJson(“/忠诚度/url”);
}
getAsJson(路径:string):承诺{
让opts=this.getRequestOptions();
log(“在getAsJson中,path=,path”);
返回此.http.get(`${environment.API_URL}${path}`,opts)
.订阅(
(res)=>{
log(“在getAsJson,res=,res中);
返回res;
},
(错误)=>{
log(“在getAsJson中,err=,err=”;
此.checkResponseRunAuthorized(错误);
}
)
}
控制台日志消息

in getAsJson, path = /loyalty/url

in loadLoyaltyDetails, data = 
Object { closed: false, _parent: null, _parents: null, _subscriptions: (1) […], syncErrorValue: null, syncErrorThrown: false, syncErrorThrowable: false, isStopped: false, destination: {…} }

Using current token

in getAsJson, path = /other/url

in getAsJson, res = {…}
    endDate: "2019-01-08"
    numberOfShiftsRequired: 18
    numberOfShiftsWorked: 0
    startDate: "2019-01-08"

in getAsJson, res = Array []
如日志消息所示,loadLoyaltyDetails首先调用getAsJson,但会立即返回一堆GobbleDeBook。然后另一个函数调用getAsJson,接收第一次调用的数据,然后是第二次调用的数据

我希望在返回第一组数据后会出现“in-loadLoyaltyDetails,data=”行


这是我无法解决的问题,即如何确保在返回数据之前不会将控件返回到loadLoyaltyDetails?

函数
subscribe
立即返回一个对象,并且在订阅的可观察对象实际发出值之前不会暂停代码的执行
SubscribeTion
对象不用于从可观察对象获取数据,而仅用于取消订阅您以前订阅的可观察对象(请注意,您不必在
HttpClient
返回的可观察对象完成时取消订阅,从而自动取消订阅)

通过调用
return this.http.get(..).subscribe(..)
可以将这个(无用的)订阅对象一直返回到
loadLoyaltyDetails()
函数中,并将其作为
数据
对象记录

相反,您应该返回可观察对象,直到您实际需要来自可观察对象的数据为止(我想这是
loadLoyaltyDetails()
)。这是您订阅的地方,在
subscribe
函数中,您可以对可观察到的对象(在您的例子中是http响应主体)执行需要执行的操作。 通常,您会将html模板中显示的某些组件变量设置为可观察对象发出的值。您甚至可以使用将订阅推迟到模板,而根本不手动订阅

如果您不需要处理完整的HttpResponse,只需要获取JSON正文并处理错误,您可以执行以下操作:

localLoyaltyDetails:LoyaltyDetails;
//请注意,此函数不返回任何内容,尤其是不返回Subscribtion对象
loadLoyaltyDetails():void{
//假设这是你需要忠诚的地方,你可以在这里订阅详细信息
this.loyalty.getLoyaltyDetails().subscribe(loyaltyDetails=>{
//在这里处理你的忠诚细节
log(“在loadLoyaltyDetails中,data=,loyaltyDetails);
this.localLoyaltyDetails=忠诚详细信息;
});
}
getLoyaltyDetails():可观察{
//在本例中,我们调用getAsJson并指定要返回的类型
//忠诚详细信息。我们从给定url的服务器获取的http响应主体,
//在这种情况下“/忠诚度/url”必须与指定的类型(忠诚度详细信息)匹配。
返回这个.callApi.getAsJson(“/忠诚度/url”);
}
//不要订阅此函数,而是在
//您实际需要来自可观察对象的数据的点。
//T是http get请求应该返回的JSON对象的类型变量。
getAsJson(路径:字符串):可观察{
让opts=this.getRequestOptions();
log(“在getAsJson中,path=,path”);
返回此.http.get(`${environment.API_URL}${path}`,opts)
.烟斗(
//您可以在此处查看数据流以进行日志记录
//但不要把这和订阅混淆了
轻触(response=>console.log(“在getAsJson中,res=,response)),
//在这里处理http错误,因为这是使用HttpClient的服务
catchError(this.handleError)
);
}
//从文件中复制
私有句柄错误(错误:HttpErrorResponse){
if(error.error instanceof ErrorEvent){
//发生客户端或网络错误。请相应地进行处理。
console.error('发生错误:',error.error.message);
}否则{
//后端返回了一个不成功的响应代码。
//回应主体可能包含了错误的线索,
控制台错误(
`后端返回代码${error.status},`+
`正文是:${error.error}`);
}
//返回带有面向用户的错误消息的可观察对象
回击投手(
“发生了不好的情况;请稍后再试。”);
};
您可以阅读中有关
HttpClient
handleError
函数的更多信息。您还可以编写一个
handleError
函数,在出现错误时返回一个默认值,如中的错误


编辑regar