父函数的返回值(嵌套);等待异步功能

时间:2014-11-21 22:09:45

标签: jquery asynchronous callback nested deferred

我对异步函数没什么困难。 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();
}

但现在我还有另外两个问题。在lower函数中,函数 $。when 本身是异步的。所以它只包装了这个问题。所以函数 chrome.webRequest.onBeforeRequest.addListener()完成,而不等待 getImageSizeByUrl()的返回。如何在这个棘手的情况下获得同步行为?

我的第二个问题是下部函数中的嵌套返回值。 返回{redirectUrl:" https://www.google.de/images/srpr/logo11w.png"}; return {} 应该是父函数函数的返回值(信息)

(背景:chrome扩展的下层监听器功能在加载之前检查每个图像。监听器需要一个返回值来重定向或允许图像加载。但是监听器功能并不等待上层的结果function 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"]
);

希望有人能够帮助我/给我一些提示。 :)
最好的问候

1 个答案:

答案 0 :(得分:0)

您可能会发现编写一个返回&#34; promisified Image&#34;的构造函数更有用,即使用返回promise的自定义window.Image方法的.setSrc()实例。< / p>

这样的事情(未经测试)应该这样做:

function PromisifiedImg() {
    var img = new Image();
    img.setSrc = function(src, limits) {
        var dfrd = $.Deferred();
        img.onload = function() {
            if(limits && (img.width > limits.width || img.height > limits.height)) {
                var error = new Error('img dimension(s) exceed limits');
                error.number = 101; // 101 is arbitrary
                dfrd.reject(error);
            } else {
                dfrd.resolve(img);
            }
        };
        img.onerror = function(e) {
            e.number = e.number || 0;
            dfrd.reject(e);
        };
        img.src = src;
        return dfrd.promise();
    };
    return img;
}

现在您可以调用返回的图片.setSrc(...)方法,而不是.src = '...'

您的....addListener()处理程序可能如下所示:

chrome.webRequest.onBeforeRequest.addListener(
    function(info) {
        var img = new PromisifiedImg();
        img.setSrc(info.url, { width:200, height:200 }).then(null, function(e) {
            if(e.number === 101) { // detect the custom error condition
                console.log(e.message);
                return img.setSrc("https://www.google.de/images/srpr/logo11w.png");
            }
        });
    },
    { urls: [ "<all_urls>" ], types: ["image"] },
    ["blocking"]
);

这样做的一个好处是返回的Image是可重用的。对.setSrc()的第二次调用将在Image的同一个实例上运行,但会返回一个新的承诺。

注意:我没有尝试将传递给它的其他参数渗透到chrome.webRequest.onBeforeRequest.addListener()包装器中。在偶然看一眼documentation后,这看起来可能是错误的做法。因此,这个答案可能只能提供部分解决方案。