记录一次重新学习SetInternal和SetTimeout

 背景:
做一个Chrome的TamperMoney脚本,采集超星慕课全部学校:http://passport2.chaoxing.com/login?fid=145&refer=http://i.mooc.chaoxing.com
这是一个二级联动的,左侧是城市、右上是26个字母,右下是要采集的学校列表,想要一次性把全部数据采集下来,必须不断点击城市和字母进行切换,数据是通过ajax异步加载后渲染到页面的。
总的来说是希望前端抓取到学校的名称和ID,用$.ajax传到自己写的ashx的方法中,再存到数据库里。

坑一:首先遇到的问题就是这样采集的数据由于跨域问题,无法$.ajax到localhost:1066/r.ashx?method=a 中,解决方式是使用JSONP

 $.ajax({
        url: "http://localhost:1066/handle/r.ashx?method=updateChaoXingSchool",
        type: "get",
        dataType:"jsonp", //使用jsonp
        jsonp:"jsonpCallback",
        jsonpCallback:"success_jsonpCallback", 
        data: {schoolId:id,name:name,letter:lt},
        success:function(result){
            csl++;
        },
        error:function(data){
        }
    });


后端context.response.write也必须和jsonpCallback中制定的方法名一致才行,里面的内容倒是无关紧要:
context.Response.Write("success_jsonpCallback({"result":true})");


思路一:使用$.each嵌套循环来做,但是$.each是异步的,而JSONP也是异步的且无法强制设定为同步,就算是可以同步,也会阻挡网页导致点击事件失效,这样切换城市和字母又无法实现了。

思路二:使用for循环+sitetimeout,因为for循环是同步方法,settimeout可以控制$.ajax的运行间隔。 用过才深刻理解了setTimeout是个异步方法,换用了各种方式设定setTimeout(如i*1000)效果也非常差,即使顺序和内容采集到是对的,也会导致浏览器卡顿崩溃。

思路三:前面的尝试让我彻底放弃了使用循环来实现,改变使用定时器SetInternal实现:定时监控整个网页的情况,来判定如何执行采集。原理:
    1、点击启动按钮:获取城市对象集合、当前学校对象集合;设定初始值,如起始城市、字母、学校的 Inex值。
    2、设定定时器A,每0.1秒采集当前页面的学校,当前学校Index自增   
    3、if(当前学校Index==当前页面总学校数)  
                            then  
                                  清除定时器A,避免在切换字母的过程中继续采集
                                  点击切换下一个字母
         else
                            采集学校数据……
 4、 设定定时器B
5、
if(当前字母Index==26)  
                            then  
                                  清除定时器B,避免在切换城市的过程中继续采集
                                  点击切换下一个城市
         else
                            采集学校数据……
                                   

最终代码:

// ==UserScript==
// @name         超星采集学校
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://passport2.chaoxing.com/*
// @require http://code.jquery.com/jquery-1.10.0.min.js
// @grant        none
// ==/UserScript==
//当前总
var cl=$(".zw_s_li a").length;
var ll=26;
var sl=$(".zw_m_li a").length;
//当前进度
var ccl=0;
var cll=1;
var csl=0;
//当前对象
var city=$(".zw_s_li a");
var school=$(".zw_m_li a");
var letter=$(".zw_m_t_li a");
var timerA;
var timerB;

function getSchool(){
    if(cll>ll){
        clearInterval(timerB);
        //如果字母都过完了,就换城市
        ccl++;
        cll=1;//重置字母
        $(city[ccl]).click();
        setTimeout(function(){
            $(letter[1]).click();
            timerB=setInterval(function(){
                getSchool();
            },1000);
        },2000);
    }
    else if(ccl>cl){
        clearInterval(timerB);
        return;
    }
    else if(csl==sl){
        //如果学校采集完了,就换字母
        clearInterval(timerB);
        cll++;
        console.log($(letter[cll]).attr("id"));
        $(letter[cll]).click();
        setTimeout(function(){
            school=$(".zw_m_li a");
            csl=0;
            sl=school.length;
            timerB=setInterval(function(){
                getSchool();
            },1000);
        },2000);
    }
    else{
        //否则一直采集学校
        console.log(ccl+"_"+cll+"/"+ll+"_"+csl+"/"+sl);
        var id=$(school[csl]).attr("id");
        var name=$(school[csl]).attr("name");
        var lt=$(letter[cll]).attr("id");
        csl++;
        insertSchool(id,name,lt);
        getSchool();
    }
}
function insertSchool(id,name,lt){
    $.ajax({
        url: "http://localhost:1066/handle/r.ashx?method=updateChaoXingSchool",
        type: "get",
        dataType:"jsonp",
        jsonp:"jsonpCallback",
        jsonpCallback:"success_jsonpCallback",
        data: {schoolId:id,name:name,letter:lt},
        success:function(result){
        },
        error:function(data){
        }
    });
}
(function() {

    $(".zw_m_box").before("<input type='button' value='采集' style='200px;height:35px;text-align:center;font-size:16px;' id='caiji'>");
    $("#caiji").click(function(){
        cl=$(".zw_s_li a").length;
        sl=$(".zw_m_li a").length;
        city=$(".zw_s_li a");
        school=$(".zw_m_li a");
        letter=$(".zw_m_t_li a");
        getSchool();
    });
})();
原文地址:https://www.cnblogs.com/cdoneiX/p/12258522.html