Angular 12中如何将回调结果赋值给组件变量?
问题描述
在Angular 12应用中,通过以下服务函数从后端获取图片:
getProfileImage(filename: string, userId: string, callback) { const url = environment.apiEndpoint + 'files/profileimage/' + filename + '/' + userId; var xhr = new XMLHttpRequest(); xhr.onload = function () { var reader = new FileReader(); reader.onloadend = function () { callback(reader.result); } reader.readAsDataURL(xhr.response); }; xhr.open('GET', url); xhr.responseType = 'blob'; xhr.send(); }
调用代码如下:
ngOnInit() { this.authService.getUser().then(response => { this.user = response; this.profileService.getProfileImage(this.user.profileImagePath, this.user.id, function(dataUrl) { this.profileImage = dataUrl; // 此处报错 console.log(this.profileImage); }); }); }
报错信息:
core.js:6479 ERROR TypeError: Cannot set properties of undefined (setting 'profileImage') at profile.page.ts:29:26 at reader.onloadend (profile.service.ts:23:17) at push.99140._ZoneDelegate.invoke (zone.js:409:1) at Object.onInvoke (core.js:28705:1) at push.99140._ZoneDelegate.invoke (zone.js:408:1) at push.99140.Zone.runGuarded (zone.js:180:1) at FileReader.<anonymous> (zone.js:163:1)
需要解决的问题:如何将dataUrl响应赋值给可在HTML中访问的组件变量?
解决方案
错误根源是普通回调函数中的this指向不是组件实例,导致无法访问profileImage变量。可以通过以下几种方式解决:
1. 使用箭头函数作为回调
箭头函数会继承外层上下文的this(即组件实例),直接替换回调函数即可:
ngOnInit() { this.authService.getUser().then(response => { this.user = response; this.profileService.getProfileImage(this.user.profileImagePath, this.user.id, (dataUrl) => { this.profileImage = dataUrl; // 此时this指向组件实例 console.log(this.profileImage); }); }); }
2. 提前保存组件的this引用
在回调外部将组件的this赋值给一个变量,回调内部使用该变量访问组件属性:
ngOnInit() { this.authService.getUser().then(response => { this.user = response; const that = this; // 保存组件的this引用 this.profileService.getProfileImage(this.user.profileImagePath, this.user.id, function(dataUrl) { that.profileImage = dataUrl; // 使用that访问组件变量 console.log(that.profileImage); }); }); }
3. 使用bind()绑定this指向
通过bind()方法显式将回调函数的this绑定为组件实例:
ngOnInit() { this.authService.getUser().then(response => { this.user = response; this.profileService.getProfileImage(this.user.profileImagePath, this.user.id, function(dataUrl) { this.profileImage = dataUrl; console.log(this.profileImage); }.bind(this)); // 绑定this为组件实例 }); }
进阶优化:将服务函数改为返回Promise
Angular中更推荐使用Promise或Observable处理异步操作,避免回调嵌套。可以修改服务函数如下:
getProfileImage(filename: string, userId: string): Promise<string> { return new Promise((resolve, reject) => { const url = environment.apiEndpoint + 'files/profileimage/' + filename + '/' + userId; const xhr = new XMLHttpRequest(); xhr.onload = () => { const reader = new FileReader(); reader.onloadend = () => { resolve(reader.result as string); }; reader.onerror = reject; reader.readAsDataURL(xhr.response); }; xhr.onerror = reject; xhr.open('GET', url); xhr.responseType = 'blob'; xhr.send(); }); }
调用时使用async/await让代码更简洁:
async ngOnInit() { this.user = await this.authService.getUser(); try { this.profileImage = await this.profileService.getProfileImage(this.user.profileImagePath, this.user.id); console.log(this.profileImage); } catch (error) { console.error('加载头像失败:', error); } }
内容的提问来源于stack exchange,提问作者quma
相关产品推荐
相关产品推荐

