如何等待异步方法的回调返回值?
Posted
技术标签:
【中文标题】如何等待异步方法的回调返回值?【英文标题】:How to wait for an asynchronous method's callback return value? 【发布时间】:2013-02-14 00:31:22 【问题描述】:我知道等待异步方法是愚蠢的,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']);
希望您在上面的代码中看到我的困境。我需要根据异步方法调用的结果返回一个对象。有没有可能做到这一点?
【问题讨论】:
当onBeforeRequest
被调用时,你不能听所有chrome.tabs
的变化并让websiteAlreadyOpenInOtherTab
已经包含正确的值吗?
我认为您处理问题的方法不正确。首先,如果事情需要异步,那么不需要同步响应,而是在模型中工作并使用异步回调,如果您决定不应该打开选项卡,则关闭它。有一个单独的 API 函数来关闭选项卡,您不需要仅从 onbeforerequest 中返回 false...
@davin:但这会导致“标签闪烁”之类的,完全不同的行为(并且会发送请求)
@Bergi 是的,差不多。 onBeforeRequest
不能包含正确的值(因为在调用 onBeforeRequest
之前我不会知道它。但我可以维护某种了解打开选项卡的结构。这是一个走动好吧。@davin +1关于@Bergi的论点。在我的用例中发送请求并关闭选项卡是不可接受的。该请求应该被取消。但无论如何感谢您的建议。:)
【参考方案1】:
也许您可以通过跟踪标签 URL 来解决问题?:
-
应用启动时,使用
chrome.tabs.query
获取所有打开的标签页网址
订阅 chrome.tabs.onUpdated
和 chrome.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;
;
());
现在您应该可以直接在您的onBeforeRequestMethod
中询问tabUrlHandler
:
function onBeforeRequest(details)
var websiteAlreadyOpenInOtherTab = tabUrlHandler.contains(details.url);
if (websiteAlreadyOpenInOtherTab)
return cancel: true ;
【讨论】:
太棒了!感谢您提供非常详细的示例,这是我必须采取的路线。 谢谢! +1 一个有趣的问题! :)以上是关于如何等待异步方法的回调返回值?的主要内容,如果未能解决你的问题,请参考以下文章
在异步函数内部,从回调函数返回值返回 Promise(undefined) [重复]