调整异步chrome.history调用 [英] Wrangling Asynchronous chrome.history calls

查看:216
本文介绍了调整异步chrome.history调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Chrome扩展程序中,我有一组网址,我想找到第一个未访问的网址。由于 chrome.history API是异步的,我的第一本能是做一些奇怪的递归迭代,像这样...

  url = [。 ..]。 
函数recur(idx){
chrome.history.getVisits(urls [idx],function(visitItems){
if(visitItems&&&visitItems.length> 0){
//成功!
} else {
recur(idx + 1);
}
}
}
recur(0);

但是,这很糟糕(它非常难看,它可能非常慢,而且它会打破长列表) 。



有没有办法更好地将所有这些调用都转换为chrome.history?或者,是否有完全不同的选项?


<如果订单很重要,而且你的清单很长,并且找到未访问链接的可能性比以后更高,那么最好的方法是基本上做你自己的事情这是从流行的 async 库的 forEachSeries 实现。

  async.forEachSeries = function(arr,iterator,callback){
callback = callback || function(){};
if(!arr.length){
return callback();
}
var completed = 0;
var iterate = function(){
iterator(arr [completed],function(err){
if(err){
callback(err);
callback =


完成+ = 1;
if(completed === arr.length){
callback(null) ;
}
else {
iterate();
}
}
});
};
iterate();
};

您会看到您已经开始实施的相同递归模式。另一种选择是将它们全部平行并在追回时跟踪它们。只要列表中的第一个项目以未访问的方式返回,您可以立即退出。注意:以下代码未经测试...

  var url = [a,b,c,d],
unvisitedUrls = [],
count = urls.length,
done = false;

var checkUrl = function(d){
var url = d;

返回函数(visitItems){
if(done)return;
count--;

if(visitItems&&& visitItems.length> 0){
unvisitedUrls.push(url);
}
else {
urls.splice(urls.indexOf(url)); //删除访问过的网址
}

if(unvisitedUrls.indexOf(urls [0])> -1 || count === 0){
done = true ;
//完成检查网址,网址[0]是赢家
}

}
}


网址。 forEach(function(d){chrome.history.getVisits(d,checkUrl(d));});

如果您的列表长达数百万条,那么您可以批量遍历它们而不是全部一旦。以下是使用 https:// github上找到的 async 库的示例.com / caolan / async

  var checkUrl =函数(url,cb){

chrome.history.getVisits(url,function(itemVisits){

if(done)return cb();
count--;

if (visitItems&&& visitItems.length> 0){
unvisitedUrls.push(url);
}
else {
urls.splice(urls.indexOf(url) ); //删除访问的网址
}

if(unvisitedUrls.indexOf(urls [0])> -1 || count === 0){
done = true;
//完成检查网址,网址[0]是优胜者
}

cb();
}
};

async.forEachLimit(urls,50,checkUrl,function(err){doSomethingWithWinner();});


In my Chrome extension, I have an array of URLs, and I want to find the first unvisited one. Because the chrome.history API is asynchronous, my first instinct would be to do some kind of grotesque recursive iteration, like this...

urls = [...];
function recur(idx) {
    chrome.history.getVisits(urls[idx], function(visitItems) {
        if(visitItems && visitItems.length > 0) {
            // Success!
        } else {
            recur(idx + 1);
        }
    }
}
recur(0);

But, this sucks (it's really ugly, it's probably very slow, and it will break for long lists).

Is there any way to better wrangle all of these calls to chrome.history? Or, is there a totally distinct option?

解决方案

If order is important and your list is long and the probability of finding an unvisited link sooner than later is high, then the best way is basically to do what you are doing. Here is the forEachSeries implementation from a popular async library.

async.forEachSeries = function (arr, iterator, callback) {
    callback = callback || function () {};
    if (!arr.length) {
        return callback();
    }
    var completed = 0;
    var iterate = function () {
        iterator(arr[completed], function (err) {
            if (err) {
                callback(err);
                callback = function () {};
            }
            else {
                completed += 1;
                if (completed === arr.length) {
                    callback(null);
                }
                else {
                    iterate();
                }
            }
        });
    };
    iterate();
};

You'll see the same recursive pattern that you've started to implement. The other option is to kick them all off in parallel and track them as they come back. You can exit out as soon as the first item in the list comes back as unvisited. Note: the following code is untested...

var urls = [a,b,c,d],
    unvisitedUrls = [],
    count = urls.length,
    done = false;

var checkUrl = function(d) {
  var url = d;

  return function(visitItems) {
    if (done) return;
    count--;

    if (visitItems && visitItems.length > 0) {
        unvisitedUrls.push(url);
    }
    else {
        urls.splice(urls.indexOf(url));  // remove the visited url
    }

    if(unvisitedUrls.indexOf(urls[0]) > -1 || count === 0) {
        done = true;
        // done checking urls, urls[0] is the winner
    }

  }
}


urls.forEach(function(d) { chrome.history.getVisits(d, checkUrl(d)); });

If your list is millions of items long, then you can iterate through them in batches instead of all at once. Here's an example using the async library found at https://github.com/caolan/async.

var checkUrl = function(url, cb) {

  chrome.history.getVisits(url, function(itemVisits) {   

    if (done) return cb();
    count--;

    if (visitItems && visitItems.length > 0) {
        unvisitedUrls.push(url);
    }
    else {
        urls.splice(urls.indexOf(url));  // remove the visited url
    }

    if(unvisitedUrls.indexOf(urls[0]) > -1 || count === 0) {
        done = true;
        // done checking urls, urls[0] is the winner
    }

    cb();
  }
};

async.forEachLimit(urls, 50, checkUrl, function(err) { doSomethingWithWinner(); });

这篇关于调整异步chrome.history调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆