如何在Promise/async场景中正确更新this指向的属性或内部变量
问题原因
img.onload 是普通函数作为事件回调,执行时this默认指向触发事件的img实例,而非embedFromString方法所属的外层对象,所以你赋值的属性实际都挂在了img对象上,自然不会更新到目标对象上。
解决方案
共有3种常用的修复方式:
方案1:外层提前缓存this指向
兼容性最好的写法,在函数开头把外层的this存到临时变量中,回调内直接用临时变量操作属性:
embedFromString: function(url, mediaType) { const that = this; // 提前缓存外层this指向 let img = new Image, canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), src = url; let imgBase64; img.crossOrigin = "Anonymous"; img.src = src; return new Promise(((resolve, reject) => { img.onload = async function() { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); imgBase64 = canvas.toDataURL("image/png"); console.log(imgBase64, 'hello'); // 用缓存的that操作外层对象属性 that.mediaType = mediaType; that.url = imgBase64.split(',')[1]; that.base64 = true; return resolve(); } })); }
方案2:用箭头函数作为onload回调
箭头函数不会绑定自身的this,会自动继承外层作用域的this指向:
embedFromString: function(url, mediaType) { let img = new Image, canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), src = url; let imgBase64; img.crossOrigin = "Anonymous"; img.src = src; return new Promise(((resolve, reject) => { // 回调改为箭头函数 img.onload = async () => { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); imgBase64 = canvas.toDataURL("image/png"); console.log(imgBase64, 'hello'); this.mediaType = mediaType; this.url = imgBase64.split(',')[1]; this.base64 = true; return resolve(); } })); }
方案3:用bind方法绑定this
通过bind方法手动把回调的this绑定为外层的this:
embedFromString: function(url, mediaType) { let img = new Image, canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), src = url; let imgBase64; img.crossOrigin = "Anonymous"; img.src = src; return new Promise(((resolve, reject) => { img.onload = (async function() { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); imgBase64 = canvas.toDataURL("image/png"); console.log(imgBase64, 'hello'); this.mediaType = mediaType; this.url = imgBase64.split(',')[1]; this.base64 = true; return resolve(); }).bind(this); // 绑定外层this到回调函数 })); }
内容的提问来源于stack exchange,提问作者Parul
相关产品推荐
相关产品推荐

