将HTML元素传入Promise的reject函数后变为Event对象,原因何在?
问题解析:为什么传入Promise Reject的HTML元素变成了Event对象?
嘿,这个问题其实是事件回调的参数传递在搞鬼!咱们来理清楚到底发生了什么:
问题根源
你在代码里直接把reject函数赋值给了img.onerror:
img.onerror = reject
但浏览器的onerror事件触发时,会自动把对应的Event对象作为第一个参数传给回调函数。这就意味着,当图片加载失败触发onerror时,reject实际上是被这样调用的:
reject(Event对象)
而不是你原本期望的reject(img),所以在then的第二个回调里,你拿到的photo自然就是Event对象,而非原来的HTML元素。
解决方案:手动包装事件回调
我们需要把onerror的回调包装一层,手动把目标元素img传给reject,具体有两种写法:
写法一:普通函数包装
function photoCheck(img) { return new Promise( function(resolve, reject) { img.onload = () => resolve(img); // 可选:统一把img传给resolve img.onerror = function(event) { // 这里可以选择只传img,或者同时传event和img reject(img); // 如果需要错误事件信息,也可以传对象:reject({ element: img, errorEvent: event }) } img.setAttribute("src", img.getAttribute("data-src")); img.classList.remove('lazy-image'); }) }
写法二:箭头函数简化
function photoCheck(img) { return new Promise( function(resolve, reject) { img.onload = () => resolve(img); img.onerror = () => reject(img); // 箭头函数自动捕获外部的img变量 img.setAttribute("src", img.getAttribute("data-src")); img.classList.remove('lazy-image'); }) }
修改后,当你在then的错误回调里打印photo时,就会得到你一开始传入的HTML元素啦!
内容的提问来源于stack exchange,提问作者Valachio
相关产品推荐
相关产品推荐

