2013-02-28 7 views
7

Ich weiß, dass das Warten auf eine asynchrone Methode dumm ist, one should use callbacks instead. Was aber, wenn eine Drittanbieter-API zwingt, synchron zu sein?Warten auf den Callback-Rückgabewert einer asynchronen Methode?

Ich entwickle eine Chrome-Erweiterung, die den Benutzer daran hindert, Websites zu besuchen, die bereits auf einer anderen Registerkarte geöffnet sind. Ich muss im Grunde Anfragen basierend auf den URLs in offenen Tabs abbrechen. Ich möchte chrome.webRequest.onBeforeRequest wie folgt verwenden:

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']); 

Hoffentlich Sie mein Dilemma in dem obigen Code zu sehen. Ich muss ein Objekt basierend auf dem Ergebnis asynchroner Methodenaufrufe zurückgeben. Ist es möglich, dies zu erreichen?

+1

Nein, es ist nicht :-( – Bergi

+0

Können Sie nicht alle 'chrome.tabs' Änderungen anhören und haben' websiteAlreadyOpenInOtherTab' bereits den richtigen Wert, wenn 'onBeforeRequest' aufgerufen wird? – Bergi

+0

Ich denke, Sie sind approachi ng das Problem falsch. Erstens, wenn Dinge asynchron sein müssen, dann arbeiten Sie innerhalb des Modells und verwenden Sie einen asynchronen Callback, in dem, wenn Sie entscheiden, dass die Registerkarte nicht geöffnet sein sollte, Sie es schließen, anstatt eine synchrone Antwort zu erfordern. Es gibt eine separate API-Funktion, um Tabs zu schließen, Sie müssen nicht nur von der onbeforerequest false zurückgeben ... – davin

Antwort

6

Vielleicht können Sie das Problem lösen, indem Sie den Überblick über die Registerkarte URLs halten ?:

  1. Wenn die App gestartet wird, um alle geöffneten Tab URLs erhalten, indem Sie chrome.tabs.query
  2. abonnieren chrome.tabs.onUpdated und chrome.tabs.onRemoved und Hinzufügen/Entfernen/Aktualisieren der URLs, wenn sie sich ändern.

Irgendeine Art von Codebeispiel auf der documentation basiert:

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

}()); 

Jetzt sollten Sie in der Lage sein, in den tabUrlHandler direkt zu fragen Sie Ihren onBeforeRequestMethod:

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

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

Awesome! Danke für ein sehr detailliertes Beispiel, das ist die Route, die ich nehmen muss. – Sven

+0

Danke! +1 für eine interessante Frage! :) – nekman

Verwandte Themen