如何在angular rxjs订阅调用中进行嵌套javascript库promise回调



我有一个要求,每当发生错误时,我都需要收集基本的错误跟踪、IP地址和屏幕截图。

对于Ip地址,我使用这个API来获取Ip地址。getIp:'http://api.ipify.org/?format=json"。对于使用Html2画布的ScreenShot:库:https://github.com/niklasvh/html2canvas/issues/2282.

这是发生错误时触发的方法。

我添加了wait,但它不是在等待回调的响应,而是在回调执行之前返回。

最初调用

getIP(response:any)
{
// call 1
this.getIPAddress().subscribe(async(res:any)=>{ 
this.ipAddress = res.ip;  
// get an ip once ip recieved call another function

let errorRequest =  await this.logError(response); call 2
// another service call
this.logErrorRequest(errorRequest); //  send another service call to server to store the error
});
return  errorDetails;
} 

第二个电话。。在这种方法中,格式化请求。这里的截图,我需要调用javascript库html2canvas。等待此.getScreenShot((

//这里的问题是,该方法将在从promise调用获得响应之前返回一个响应。

async logError(response:any):ErrorRequest{
error={
ExceptionMessage:response.message,
ipAddress:this.ipAddress,
screenShot:await this.getScreenShot()    // next call 3.
};

return error;
}

//承诺回电

async getScreenShot() {
this.zone.runOutsideAngular(() => {
// call 4
html2canvas(document.querySelector("#capture")).then(canvas => {
canvas.toBlob(function(blob){
let link = document.createElement("a");
link.download = "image.png";
link.href = URL.createObjectURL(blob);
link.click();
let screenShot = blob; 
this.screenShot = blob;
},'image/png');

//your code
})   
});

除了Promise<void>之外,您不会从getScreenShot()返回任何内容,但这只是因为async。前两个调用也感觉不相互依赖,所以你可以并行进行:

这意味着,为了解决您的问题,您需要重构getScreenShot()方法:

getScreenShot() {
return this.zone.runOutsideAngular(async () => {
const canvas = await html2canvas(document.getElementById("capture"));
return new Promise(
(resolve) => canvas.toBlob((blob) => resolve(blob), 'image/png')
);
});
}

简而言之,返回this.zone调用,等待html2canvas调用,创建一个新的promise并在您的决心中返回它。另外,不要使用function关键字,因为这会扰乱this上下文。


需要重构代码的较长修复程序如下所示:

logError(response: { message: string }): void {
forkJoin([
this.getIPAddress(),
this.getScreenShot()
]).pipe(
concatMap(([ { ip }, screenshot ]) => this.logErrorRequest({
ExceptionMessage: response.message,
ipAddress: ip,
screenshot
}))
).subscribe({
next: () => console.log('error logged'),
error: () => console.log('make sure to catch this to prevent loop!')
});
}

这显然将使用重构的getScreenShot方法。正如您可能看到的,这一点要清楚得多,并且避免了使用随机this赋值。这是一个很好的流,就像rxjs想要东西一样。

还要确保以某种方式取消对错误的日志记录/分组,以防止记录大量错误或无限循环的错误。相信我,它发生了:D

最新更新