【发布时间】:2014-11-21 22:09:45
【问题描述】:
我对异步函数没什么问题。 getImageSizeByUrl() 中的异步函数可以使用 $.Deferred() 来处理。
function getImageSizeByUrl(url) {
var deferredReady = $.Deferred();
var tmpImg = new Image();
tmpImg.src = url;
// asynchronous function
$(tmpImg).on('load',function(){
getImageSizeByUrlWidth = tmpImg.width;
getImageSizeByUrlHeight = tmpImg.height;
deferredReady.resolve();
});
return deferredReady.promise();
}
但是现在我还有另外两个问题。在较低的函数中,函数 $.when 本身是异步的。所以它只解决了问题。这样chrome.webRequest.onBeforeRequest.addListener()函数就完成了,无需等待getImageSizeByUrl()的返回。在这种棘手的情况下,如何获得同步行为?
我的第二个问题是低层函数中的嵌套返回值。 return {redirectUrl: "https://www.google.de/images/srpr/logo11w.png"}; 和 return {} 应该是父函数 function(info) 的返回值。
(背景:chrome扩展的lower listener函数会在加载前检查每张图片。listener需要一个返回值来重定向或允许图片加载。但是listener函数不会等待upper函数getImageSizeByUrl的结果并返回一个空值。)
// listener for image loading
chrome.webRequest.onBeforeRequest.addListener(
function(info) {
console.log("test1");
$.when(
getImageSizeByUrl(info.url)
).done(
function() {
// for example: if image has to big height or width, load alternative image
if(getImageSizeByUrlHeight > 200 || getImageSizeByUrlWidth > 200) {
// load alternative image
console.log("test3");
return {redirectUrl: "https://www.google.de/images/srpr/logo11w.png"};
} else {
// image is not big. allow loading
console.log("test3");
return {};
}
}
);
console.log("test3");
},
{
urls: [
"<all_urls>",
],
types: ["image"]
},
["blocking"]
);
希望有人能够帮助我/给我一些提示。 :)
最好的问候
【问题讨论】:
-
哇,现在我们每天有近 20 次询问如何从异步操作同步返回值。它根本无法完成,并且编写期望只是浪费代码的代码,需要对其进行重组以与异步操作一起使用。请阅读此stackoverflow.com/questions/14220321/… 以了解您的选择(提示您代码中的答案将在于正确使用 Promise 以将异步返回值传递给其他代码,并且由于 Promise 最终使用回调,这就是您将使用的.
-
如果
onBeforeRequest处理程序必须返回只能通过异步操作获得的值,那么您根本无法使代码以这种方式工作。您将需要一个不依赖于返回异步检索值的新设计。您要么需要提前获取这些值(因此它们已经可用),要么不使用 onBeforeRequest 并以其他方式解决您的整体问题。 -
仅供参考,您根本不需要
$.when()。你可以这样做getImageSizeByUrl(info.url).done(...);$.when()只有当你想在多个承诺都完成时得到通知时才需要。 -
我还可能提到您的
getImageSizeByUrl()存在潜在问题。您需要在设置.src属性之前设置load事件处理程序。这是因为如果图像在浏览器缓存中,当您设置.src属性时,某些浏览器(如某些版本的 IE)会立即触发load事件。如果您的代码发生这种情况,您将错过load事件。因此,只需将.src的设置移至安装load事件处理程序之后即可。 -
感谢您的回答。我读了另一个几乎同样问题的问题。 stackoverflow.com/questions/9121902/… 好像你说的不改变代码布局是没有办法解决这个问题的。
标签: jquery asynchronous callback nested deferred