2013-02-28 178 views
7

我知道等待異步方法很笨,one should use callbacks instead。但是如果第三方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']); 

希望你看到我的困境在上面的代碼。我需要根據異步方法調用的結果返回一個對象。是否有可能實現這一目標?

+1

不,這不是:-( – Bergi 2013-02-28 00:10:33

+0

當你調用'onBeforeRequest'時,你不能聽所有'chrome.tabs'的變化,並且'websiteAlreadyOpenInOtherTab'已經包含正確的值嗎? – Bergi 2013-02-28 00:12:20

+0

我覺得你很親切不正確地解決問題。首先,如果事情需要是異步的,那麼不需要同步響應,而是在模型中工作,並使用異步回調,如果您決定選項卡不應該打開,則關閉它。有一個單獨的API函數來關閉標籤,你不需要僅僅從onbeforerequest返回false ... – davin 2013-02-28 00:23:31

回答

6

也許您可以通過跟蹤標籤的網址?:通過使用chrome.tabs.query

  • 解決問題

    1. 當應用程序啓動後,得到所有打開的標籤網址訂閱chrome.tabs.onUpdatedchrome.tabs.onRemoved並在更改時添加/刪除/更新URL。

    某種類型的代碼示例的基礎上documentation

    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; 
        } 
        }; 
    
    }()); 
    

    現在你應該可以直接問tabUrlHandleronBeforeRequestMethod

    function onBeforeRequest(details) { 
        var websiteAlreadyOpenInOtherTab = tabUrlHandler.contains(details.url); 
    
        if (websiteAlreadyOpenInOtherTab) { 
        return { cancel: true }; 
        } 
    } 
    
  • +0

    太棒了!感謝一個非常詳細的例子,這是我必須採取的路線。 – Sven 2013-02-28 08:01:58

    +0

    謝謝!爲一個有趣的問題+1! :) – nekman 2013-02-28 09:24:56