9

我知道等待异步方法是愚蠢的,应该使用回调来代替。但是,如果第三方 API 强制您进行同步怎么办?

我正在开发一个 Chrome 扩展程序,它将阻止用户访问已经在另一个选项卡中打开的网站。我基本上需要根据打开的标签中的 url 取消请求。我想这样使用chrome.webRequest.onBeforeRequest

function onBeforeRequest(details) {
  var websiteAlreadyOpenInOtherTab;

  // Here i want to set `websiteAlreadyOpenInOtherTab` by using the `chrome.tabs`
  // API. It's asynchronous though and that's my problem. I cant return a value
  // from an asynchronous method call.

  if (websiteAlreadyOpenInOtherTab) {
    return { cancel: true };
  }
}

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

希望您在上面的代码中看到我的困境。我需要根据异步方法调用的结果返回一个对象。有可能实现这一目标吗?

4

1 回答 1

6

也许您可以通过跟踪标签 URL 来解决问题?:

  1. 当应用程序启动时,通过使用获取所有打开的选项卡 URLchrome.tabs.query
  2. 订阅chrome.tabs.onUpdatedchrome.tabs.onRemoved在 URL 更改时添加/删除/更新 URL。

基于文档的某种代码示例:

var tabUrlHandler = (function() {
   // All opened urls
   var urls = {},

   queryTabsCallback = function(allTabs) {
      allTabs && allTabs.forEach(function(tab) {
          urls[tab.id] = tab.url;
      });
   },

   updateTabCallback = function(tabId, changeinfo, tab) {
       urls[tabId] = tab.url;
   },

   removeTabCallback = function(tabId, removeinfo) {
       delete urls[tabId]; 
   };

   // init
   chrome.tabs.query({ active: true }, queryTabsCallback);
   chrome.tabs.onUpdated.addListener(updateTabCallback);
   chrome.tabs.onRemoved.addListener(removeTabCallback);

   return {
     contains: function(url) {
        for (var urlId in urls) {
           if (urls[urlId] == url) {
              return true;
           }
        }

        return false;
     }
   };

}());

现在您应该可以tabUrlHandler直接在您的onBeforeRequestMethod:

function onBeforeRequest(details) {
  var websiteAlreadyOpenInOtherTab = tabUrlHandler.contains(details.url);

  if (websiteAlreadyOpenInOtherTab) {
    return { cancel: true };
  }
}
于 2013-02-28T07:51:09.060 回答