动手写chrome扩展-bookmarkd

上次刚写完holmes扩展的分析,这个月的文章还在犯愁,于是动手写了一个扩展,顺便扩充一下chrome扩展开发知识点。

关于书签和标签页的api,就不多描述了,可以参考上一篇的介绍.

说说为什么要做一个书签检验吧,几年前我装过一个扩展,忘记名字了,也是做书签链接失效检验的,但是用的时候发现,效果不如意,链接明明正常,却分析说失效了,觉得莫名其妙,于是我就卸载了。

最近整理了一下书签收藏夹,还挺多的,也发现有些书签链接的确已经失效了,比如一些个人博客链接,有些人可能改了地址或者不续费不维护了,收藏的文章就都失效了。于是,想着要不自己来写一个,已经不是当年的懵逼,至少扩展,还是能写的,这不,刚写完的扩展bookmarkd,不过貌似发布要付费啊登录啊啥的,想想,可能实现也有点半吊子,就放着吧。个人用。

原理

基本上,我们知道bookmarks这个api ,就能做很多事了,holmes主要是收集书签数据作为搜索数据库内容,而我这里要实现的是针对这些书签进行一一请求校验。 原理很简单吧!

分析

虽然原理很简单,但实现起来不细心是不行的,先列一下要做的主要步骤。

因为书签比较多,要展示应该是一个完整的页面,所以考虑的是点击扩展图标打开网页。

其次,利用bookmarks的接口获取所有书签数据。

再者,就可以遍历每一个书签,进行链接请求了,问题来了,链接肯定涉及到不同域的情况,扩展的操作页应当属于本地域,那跨域没后端配合不就没法做了?

淡定!我们可以看这里,作为扩展的存在,跨域的问题,谷歌粑粑肯定想好了,那就是直接用XMLHttpRequest,也就是平常用的ajax,就能够直接跨域了,当然要配置一下,允许的域名,因为是书签,域名不定,所以设置为所有。

配置字段如下:

{
  "permissions":[
     "bookmarks", "tabs", "chrome://favicon/",
     "http://*/",
     "https://*/" 
     ]
 }

这样,我们就能无忧无虑地进行跨域请求了。

请求完数据,当然就是将对应的状态码返回给每个书签数据,最后连通状态码一起展示出来,并提供删除书签功能。

细节

通过简要分析,似乎一切畅通无阻,但开发过程还是遇到些许问题。

一、 比较愚蠢,但也是知识点:如何设置点击扩展图标打开页面,这个需要知道browserAction这个接口,我们可以利用其onClicked绑定事件来新开标签页打开项目的index.html,代码如下:

function bindEvent(){
    window['chrome']['browserAction']['onClicked']['addListener'](function(e) {
        var newURL = "index.html";
      chrome.tabs.create({ url: newURL });
    });
}
bindEvent();

那么这段代码应该放在哪里,怎么触发呢?

这个时候我们要设置配置文件的background字段:

   "background": {
      "scripts":["js/bkg.js"]
   }

该字段定义了扩展的后台脚本,扩展系统在启动时就会执行bkg的脚本,这段脚本就承载着刚才提到的代码。于是就给图标点击绑定了事件。

说了这么多,还没说遇到了啥问题,那就是在我第一次用的时候,老想着检测一下这段脚本会不会被多次触发以及如何验证脚本已执行,结果写了console.log一直没有输出,后来一想,不对,这是后台脚本,你哪来对应的控制台查看console!!!

二、 异步编程

首先,书签数据的获取,其实getTree方法是一个异步方法,所以我们的遍历书签应当在异步回调中或者回调之后才能遍历。

再者,遍历书签时,对每个请求进行校验也是异步过程,于是我们需要在异步回调中做一个标记判断,当所有书签请求都发出去并回调之后,才执行最后的总结工作(每个请求响应后为书签数据元素添加status属性,总结则是对最后的书签数据进行模板替换并输出到页面)

伪代码如下:

time = urls.length;
urls.forEach(function(e,index){
   async(e,function(res){
       urls[index]['status'] = res;
       --time;
       if(time===0){
           cbk()
       }
   }) 
})

三、 实际请求时,几百条甚至上千的书签,每一个都发起get请求是一件很奢侈很耗时的事,于是我改用了head请求,head请求只是服务器响应响应头内容,浏览器则不必为每一个get请求做响应报文获取,尽管改成head请求,处理也是比较耗时的,查看了下六百多条书签,检验完毕用了十多分钟,可怕。

于是我增加了一个新功能,给每个书签增加一个检测按钮,用于单挑数据get请求。为什么改用get了呢,因为每次只是单条请求的处理,并不会耗多长时间。

而且,在用head请求过程中,发现一些网站网页能打开,但是head请求响应404,或者其他,很是奇怪,我以为get请求一定伴有head请求,可事实貌似并非如此。

写到这,貌似把逻辑基本概况描述了一遍,本想做个不错的扩展,发现在耗时方面没有多大建树,想起以前用的扩展之所以卸载的理由,和真正实现时遇到的情况,大概有所呼应吧,在想,还有没有更好的方式来实现链接检测呢?