在阻塞的webRequest处理程序中使用异步调用 [英] Use asynchronous calls in a blocking webRequest handler

查看:80
本文介绍了在阻塞的webRequest处理程序中使用异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用browser.webRequest.onBeforeRequest处理程序.我需要阻止webRequest,直到获得从处理程序内对异步方法的调用返回的信息为止.我该怎么办?

I'm using a browser.webRequest.onBeforeRequest handler. I need to block the webRequest until I have information back from calls to asynchronous methods made within the handler. How can I do that?

首先,我对这个长期的问题表示歉意.但我希望有人能提供帮助.

First, my apology for the long question. But I hope someone can help.

我有一个包含browser.webRequest.onBeforeRequest的嵌入式扩展(我现在需要使用嵌入式扩展来处理一些SDK旧代码).

I have an embedded extension which contains a browser.webRequest.onBeforeRequest (I need to use embedded extension at the moment to deal with some SDK legacy code).

browser.webRequest.onBeforeRequest回调函数连接到SDK扩展,并指示其执行某些功能.完成任务后,SDK会将答复发送到webextension.我在browser.runtime.sendMessage中使用了await来确保停止执行,直到得到SDK的答复为止.要使用await,我必须使用async(但实际上我不希望使用async函数).当我不使用await时,我只会在循环完成所有迭代之后才从SDK获得答复,而不是针对每个迭代.

The browser.webRequest.onBeforeRequest callback function connects to an SDK extension and instructs it to perform some functions. The SDK sends reply to the webextension when it is done from the task. I used await in the browser.runtime.sendMessage to ensure that I stop the execution until I get a reply from SDK. To use await, I had to use async (but in fact I do not want async function). When I do not use await, I only get the reply from the SDK after the loop finishes all its iterations and not for each iteration.

下面的示例代码包含许多控制台消息,这些消息用于调试以仅监视执行情况.

The sample code below contains a lot of console messages for debugging just to monitor the execution.

问题是:我没有得到可靠的结果.在某些情况下(并非全部),http请求在SDK代码生效之前就消失了.我可以确定这一点,因为请求属性必须受到SDK代码的影响.控制台将按预期显示执行顺序.但是,http请求不受SDK的影响(在某些情况下).

The problem is: I am not getting a reliable outcome. In some cases (not all), the http request goes out before the SDK code is effective. I could identify this because the request properties must be affected by the SDK code. The console shows the execution sequence as expected. But, the http request is not affected by the SDK (in some cases).

在这个简单的示例中,SDK只是向网络扩展发送了一条消息,但假定它执行某些功能,读/写操作等.所有SDK任务必须在请求发出之前完成.

In this simple example, the SDK just sends a message to the webextension, but assume that it performs some functions, read/write operations, etc. All the SDK tasks must be completed before the request goes out.

我真正需要的是确保在执行所有SDK代码之前,Web请求不会消失.

What I really need is to guarantee that the web request will NOT go out until all the SDK code is performed.

参考MDN文档,它表示browser.webRequest.onBeforeRequest是async函数.我想知道这是否是问题的根源?如果是这样,如何强制使其同步?

Reference to MDN documentation, it says that the browser.webRequest.onBeforeRequest is an async function. I wonder if this is the source of the problem? if so, how to enforce it to be sync?

embedding-extension [directory]
    - index.js
    - package.json
    - webextension [directory]
       - main.js
       - manifest.json

1)package.json:

{
  "title": "testhybrid",
  "name": "testhybrid",
  "version": "0.0.1",
  "description": "A basic add-on",
  "main": "index.js",
  "author": "",
  "engines": {
    "firefox": ">=38.0a1",
    "fennec": ">=38.0a1"
  },
  "license": "MIT",
  "hasEmbeddedWebExtension": true,
  "keywords": [
    "jetpack"
  ]
}

2)index.js:

const webExtension = require("sdk/webextension");
console.log("in SDK: inside embedding extension");

// Start the embedded webextension
  webExtension.startup().then(api => {
    const {browser} = api;
    browser.runtime.onMessage.addListener((msg, sender, sendReply) => {
      if (msg == "send-to-sdk") {
         console.log("in SDK: message from webExt has been received");
        sendReply({
          content: "reply from SDK"
        }); //end send reply
      }//end if

    }); //end browser.runtime.onMessage

  }); //end webExtension.startup

3)manifest.json:

{
  "manifest_version": 2,
  "name": "webExt",
  "version": "1.0",
  "description": "No description.",
  "background": {
    "scripts": ["main.js"]
  },

  "permissions": [
    "activeTab",
    "webRequest",
  "<all_urls>"
],

"browser_action": {
  "default_icon": {
    "64": "icons/black-64.png"
  },
  "default_title": "webExt"
}
}

4)main.js:

var flag=true;
async function aMethod() {
  console.log("in webExt: inside aMethod");
  for(var x=0; x<2; x++)
  {
    console.log("loop iteration: "+x);
    if(flag==true)
      {
        console.log("inside if");
        console.log("will send message to SDK");
        const reply = await browser.runtime.sendMessage("send-to-sdk").then(reply => {
        if(reply)
        {
          console.log("in webExt: " + reply.content);
        }
        else {
           console.log("<<no response message>>");
        }
        });
      }//end if flag

    else
      {
        console.log("inside else");
      }//end else
  }//end for
}

browser.webRequest.onBeforeRequest.addListener(
  aMethod,
  {urls: ["<all_urls>"],
   types: ["main_frame"]}
);

推荐答案

The webRequest.onBeforeRequest documenation states (emphasis mine):

要取消或重定向请求,请首先在extraInfoSpec数组参数中将"blocking"包含在addListener()中.然后,在监听器函数中,返回 BlockingResponse 对象,设置适当的属性:

To cancel or redirect the request, first include "blocking" in the extraInfoSpec array argument to addListener(). Then, in the listener function, return a BlockingResponse object, setting the appropriate property:

  • 要取消请求,请添加值为true的属性cancel.
  • 要重定向请求,请包含一个属性redirectUrl,其值设置为您要重定向到的URL.
  • to cancel the request, include a property cancel with the value true.
  • to redirect the request, include a property redirectUrl with the value set to the URL to which you want to redirect.

从Firefox 52开始,侦听器可以返回

From Firefox 52 onwards, instead of returning BlockingResponse, the listener can return a Promise which is resolved with a BlockingResponse. This enables the listener to process the request asynchronously.

您似乎没有完成上述任何一项操作.因此,事件是完全异步处理的,不可能将请求延迟到处理程序返回之前.换句话说,如当前所写,您的webRequest.onBeforeRequest对webRequest绝对没有影响.刚刚通知您的处理程序webRequest正在处理.

You appear to have done none of the above. Thus, the event is handled completely asynchronously, with no possibility of delaying the request until your handler returns. In other words, as currently written, your webRequest.onBeforeRequest has absolutely no effect on the webRequest. You handler is just notified that the webRequest is in process.

要完成所需的操作,请延迟请求,直到执行一些异步操作之后,您需要:

To accomplish what you desire, delay the request until after you perform some asynchronous operations, you would need to:

  1. "webRequestBlocking"添加到您的 manifest.json 权限:

  "permissions": [
    "activeTab",
    "webRequest",
    "webRequestBlocking",
    "<all_urls>"
  ],

  • extraInfoSpec数组参数中的"blocking"传递给addListener():

  • Pass "blocking" in the extraInfoSpec array argument to addListener():

    browser.webRequest.onBeforeRequest.addListener(
      aMethod,
      {urls: ["<all_urls>"],
       types: ["main_frame"]},
      ["blocking"]
    );
    

  • 从处理程序中返回一个Promise,并使用BlockingResponse进行解析:

  • Return a Promise from your handler, which resolves with a BlockingResponse:

    function aMethod() {
        //Exactly how this is coded will depend on exactly what you are doing.
        var promises = [];
        console.log("in webExt: inside aMethod");
        for (var x = 0; x < 2; x++) {
            console.log("loop iteration: " + x);
            if (flag == true) {
                console.log("inside if");
                console.log("will send message to SDK");
                promises.push(browser.runtime.sendMessage("send-to-sdk").then(reply => {
                    if (reply) {
                        console.log("in webExt: " + reply.content);
                    } else {
                        console.log("<<no response message>>");
                    }
                });
            } else {
                console.log("inside else");
            }
        }
        return Promise.all(promises).then(function(){
            //Resolve with an empty Object, which is a valid blockingResponse that permits
            //  the webRequest to complete normally, after it is resolved.
            return {};
        });
    }
    

  • 这篇关于在阻塞的webRequest处理程序中使用异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆