2013-02-28 11 views
7

So che aspettare un metodo asincrono è stupido, one should use callbacks instead. Ma cosa succede se un'API di terze parti ti obbliga ad essere sincrono?Come attendere il valore di ritorno della callback di un metodo asincrono?

Sto sviluppando un'estensione per Chrome che impedirà all'utente di visitare siti Web già aperti in un'altra scheda. Fondamentalmente ho bisogno di cancellare le richieste in base agli url nelle schede aperte. Voglio usare chrome.webRequest.onBeforeRequest come questo:

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

Speriamo che si vede il mio dilemma nel codice sopra. Devo restituire un oggetto in base al risultato delle chiamate al metodo asincrono. È possibile raggiungere questo?

+1

No, non è :-( – Bergi

+0

Non puoi ascoltare tutte le modifiche di 'chrome.tabs' e avere' websiteAlreadyOpenInOtherTab' già contenente il giusto valore quando viene chiamato 'onBeforeRequest'? – Bergi

+0

Penso che tu sia approachi ng il problema in modo errato. In primo luogo, se le cose devono essere asincrone, invece di richiedere una risposta sincrona, lavorare all'interno del modello e utilizzare una richiamata asincrona in cui se si decide che la scheda non deve essere aperta, la si chiude. C'è una funzione API separata per chiudere le schede, non è necessario restituire false solo da onbeforerequest ... – davin

risposta

6

Forse è possibile risolvere il problema tenendo traccia della scheda URL ?:

  1. Quando l'applicazione si avvia, ottenere tutti gli URL scheda aperta utilizzando chrome.tabs.query
  2. Sottoscrivi chrome.tabs.onUpdated e chrome.tabs.onRemoved e aggiungere/rimuovere/aggiornare gli URL quando cambiano.

Una specie di codice di esempio in base alla 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; 
    } 
    }; 

}()); 

Ora si dovrebbe essere in grado di chiedere il tabUrlHandler direttamente in onBeforeRequestMethod:

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

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

Fantastico! Grazie per un esempio molto dettagliato, questa è la strada che devo percorrere. – Sven

+0

Grazie! +1 per una domanda interessante! :) – nekman

Problemi correlati