javascript - 如何在角度 rxjs 订阅调用中执行嵌套的 javascript 库承诺回调
问题描述
每当发生错误时,我都有一个要求,我需要收集基本的错误跟踪、IP 地址和屏幕截图。
对于 IP 地址,我使用这个 API 来获取 IP 地址。getIp:'http://api.ipify.org/?format=json'。对于使用 Html2 Canvas 的屏幕截图:库:https://github.com/niklasvh/html2canvas/issues/2282。
这是发生错误时触发的方法。
我添加了等待,但它没有等待回调的响应,它将在回调执行发生之前返回。
最初调用
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
})
});
解决方案
你没有从你的 . 中返回任何东西getScreenShot()
,Promise<void>
但那只是因为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
电话,创建一个新的承诺并在你的解决方案中返回它。另外,不要使用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
推荐阅读
- solidity - 在solidity中使用struct内部的数组
- linux - 如何在 CMake (CMakeLists.txt) 中使用 Windows 命令?
- python - 在 Python 中对对象列表执行排序时在对象中插入字段
- sql-server - 带参数的 SQL 任务 MDX。SSIS
- c# - 在 Linux 上使用 C#/Mono 处理外部媒体
- odoo-view - 如何在 odoo12 中使用自定义字段填充下拉列表?
- android - 即使背景未设置为白色,工具栏背景默认为白色
- python - 使用 SMOTE 和 ADASYN 平衡图像数据集
- ruby - 如何使用“ruby-progressbar”根据已处理项目的数量而不是“成本”的数量来显示进度?
- azure - apache-spark 中的 copyMerge 方法无限期运行