Javascript Chrome扩展:如何从onBeforeRequest函数调用同步请求

Javascript Chrome扩展:如何从onBeforeRequest函数调用同步请求,javascript,google-chrome-extension,Javascript,Google Chrome Extension,我正试图截获对mysite.com的请求。然后我想通过api.service.com了解mysite.com的真实镜像 manifest.json: { "name": "InterceptMySite", "version": "0.1", "description": "My first Chrome extension", "permissions": ["webRequest", "webRequestBlocking", "cookies",

我正试图截获对mysite.com的请求。然后我想通过api.service.com了解mysite.com的真实镜像

manifest.json

{
    "name": "InterceptMySite",
    "version": "0.1",
    "description": "My first Chrome extension",
    "permissions": ["webRequest", "webRequestBlocking", "cookies",
                    "*://mysite.com/*", "*://api.service.com/*"],
    "background": {
        "scripts": ["background.js"]
    },

    "manifest_version": 2
}
var mirror_url = false;
function setMirrorUrl() {
    var req = new XMLHttpRequest();
    req.open('GET', 'http://api.service.com', false); // sync request
    req.send(null);
    req.onload = function() {
        mirror_url = this.getResponseHeader('Mirror-Url');
    }
    return mirror_url;
}
function getMirrorUrl() {
    chrome.cookies.get({url:'http://api.service.com',name:'mirror_url'}, function(cookie) {
        if ( ! cookie)
            return setMirrorUrl();
        else
            return cookie.value;
    });
}
chrome.webRequest.onBeforeRequest.addListener(
    function(info) {
        if(info.url.indexOf('api.service.com') != -1)
            return {cancel:false};

        getMirrorUrl();

        return {redirectUrl: info.url.replace(/mysite.com/i, mirror_url)};
    },
    // filters
    {
        urls: [
            "*://mysite.com/*",
            "*://api.service.com/*"
        ]
    },
    // extraInfoSpec
    ["blocking"]
);
background.js

{
    "name": "InterceptMySite",
    "version": "0.1",
    "description": "My first Chrome extension",
    "permissions": ["webRequest", "webRequestBlocking", "cookies",
                    "*://mysite.com/*", "*://api.service.com/*"],
    "background": {
        "scripts": ["background.js"]
    },

    "manifest_version": 2
}
var mirror_url = false;
function setMirrorUrl() {
    var req = new XMLHttpRequest();
    req.open('GET', 'http://api.service.com', false); // sync request
    req.send(null);
    req.onload = function() {
        mirror_url = this.getResponseHeader('Mirror-Url');
    }
    return mirror_url;
}
function getMirrorUrl() {
    chrome.cookies.get({url:'http://api.service.com',name:'mirror_url'}, function(cookie) {
        if ( ! cookie)
            return setMirrorUrl();
        else
            return cookie.value;
    });
}
chrome.webRequest.onBeforeRequest.addListener(
    function(info) {
        if(info.url.indexOf('api.service.com') != -1)
            return {cancel:false};

        getMirrorUrl();

        return {redirectUrl: info.url.replace(/mysite.com/i, mirror_url)};
    },
    // filters
    {
        urls: [
            "*://mysite.com/*",
            "*://api.service.com/*"
        ]
    },
    // extraInfoSpec
    ["blocking"]
);
API在自定义响应头“镜像URL”(响应体为空)中返回镜像URL。此外,API还将镜像URL存储到cookie“mirror_URL”,过期时间为3小时后

在对mysite.com的第二次和后续截获请求中,所有请求都可以正常工作:mysite.com URL被存储在cookie中的实际镜像URL替换


但是在对mysite.com的第一个请求中(当没有带有镜像url的cookie时),主机url被替换为“未定义”,因为onBeforeRequest侦听器在完成之前返回redirectUrl。为什么?XMLHttpRequest对象(在setMirrorUrl()函数中)设置为sync请求。

因为
setMirrorUrl
函数执行一些异步工作,当函数返回AJAX请求时,因此,当调用
setMirrorUrl
函数mirror\uURL为false时,使用该函数可以执行一些异步工作,但仍然会从函数中返回false。这里的解决方案是使您自己的函数也同步

即使HTTP请求是同步的,对onload函数的调用仍然是异步的

试试这样的

    function setMirrorUrl(callback) {
        var req = new XMLHttpRequest();
        req.open('GET', 'http://api.service.com', false); // sync request
        req.send(null);
        req.onload = function() {
            callback(this.getResponseHeader('Mirror-Url'));
        }
    }
    function getMirrorUrl(callback) {
        chrome.cookies.get({url:'http://api.service.com',name:'mirror_url'}, function(cookie) {
            if ( ! cookie)
                return setMirrorUrl(callback);
            else
                return callback(cookie.value);
        });
    }
    chrome.webRequest.onBeforeRequest.addListener(
        function(info) {
            if(info.url.indexOf('api.service.com') != -1)
                return {cancel:false};

            getMirrorUrl(function(mirror_url){

                return {redirectUrl: info.url.replace(/mysite.com/i, mirror_url)};

            });

        },
        // filters
        {
            urls: [
                "*://mysite.com/*",
                "*://api.service.com/*"
            ]
        },
        // extraInfoSpec
        ["blocking"]
    );

六羟甲基三聚氰胺六甲醚。。。现在我在getMirrorUrl()函数中得到了正确的mirror\uURL变量,但是。。。现在它不影响onBeforeRequest侦听器函数。即使我将getMirrorUrl return更改为“return{cancel:true}”-在getMirrorUrl()完成之前请求侦听器完成之前,什么都没有发生。我可以看出,您处理的是所有异步的问题,因此您需要向所有函数发送回调以获得正确的行为。所以不要依赖于返回值,而是依赖于回调,这是javascript中处理这类事情的标准方法。