Ajax-hook拦截全局ajax请求操作

作者:matrix 发布时间:2017年12月13日星期三 分类:零零星星

github项目地址:https://github.com/wendux/ajax-hook/blob/master/src/ajaxhook.js

项目页面中有很多ajax接口请求,每次需要手动判断数据code进行错误消息提示,再加上有些使用jQuery,有些使用fetch操作,要是能有一个统一的$.ajaxSetup那就爽翻。搜索下ajax的全局拦截,有大神写好了,打开即食,NICE。代码量不大,大致的原理好像是把内置的XMLHttpRequest对象给代理了,克隆一份,进行伪装。请求操作都是通过的代理层,拦截、修改操作也都是可以的~

使用

加载ajaxhook.js文件,代码中给浏览器window对象注册全局方法:hookAjax,unHookAjax。

hookAjax //挂载拦截钩子
unHookAjax() //取消ajax请求代理

拦截处理操作

hookAjax方法注册拦截的切入点,执行回调操作。
这里用到onload 即请求完成获取数据的时候。
代码是放在vue项目里面,手动挂载DOM。若出现第一次错误请求没有成功拦截的情况,那就需要把代码放置在头部。

        //全局监听ajax请求,用于提示会话过期,和其他的错误消息。
        if ('function' === typeof(hookAjax)) {
            hookAjax({
                onload: function (xhr) {
                    if (xhr.status >= 500) return layer.alert('服务器报错,请联系管理员!'+"</br>请求地址:</br>"+xhr.responseURL, {icon: 2, title: '无形之刃 <3'});
                    var data = JSON.parse(xhr.responseText);
                    if (!!data) {
                        if (data.code !== 0) {
                            if (!!data.msg) {
                                layer.alert(data.msg, {icon: 2, title: 'ERROR'});
                            }
                        }
                    }
                }
            })
        }

拦截函数 如:onload 返回值是一个boolean,如果为true会阻断ajax请求,默认为false,不会阻断请求。

参考:
http://www.jianshu.com/p/9b634f1c9615

ajax后退操作解决办法

作者:matrix 发布时间:2017年9月19日星期二 分类:零零星星

使用github项目

https://github.com/browserstate/history.js

问题场景

移动端网页列表(上拉加载执行ajax请求)中要在点击item详情页跳转后可返回,且返回页面中需要看到或定位到点击的来源位置。

测试

要实现准确定位,刚开始想的基本原理也就是俩页面之间跳转传递分页数和滚动条位置的数量,想过sessionstorage对象来存储或是用url中hash值、query参数来传递相关状态,列表页面中进行判断请求数据且修改ajax加载的分页起始数,但是url中的参数需要和后台进行协调才可以达到满意的效果,实现起来也麻烦。搜索找到好多方案 貌似history.js兼容各大浏览器,效果应该比较理想。

JQ后加载History的js文件:/history.js/scripts/bundled/html4+html5/jquery.history.js

测试分页使用scrollPagination的JQ插件实现翻页:

var urlscroll   = '';
var p = 1;

//获取缓存数据
//dom数据以及分页起始数
var dom = !!History.getState().data.dom?History.getState().data.dom:'';
var page = !!History.getState().data.p?History.getState().data.p:p;
p = page;
$(".test_list").append(dom);//追加缓存的dom
//end

$('.test_list').scrollPagination({
    'contentPage': urlscroll, // the url you are fetching the results
    'contentData': {'page':p}, // these are the variables you can pass to the request, for example: children().size() to know which page you are
    'scrollTarget': $(window), // who gonna scroll? in this example, the full window
    'heightOffset': 0, // it gonna request when scroll is 10 pixels before the page ends
    'bottomHeight': $('.footer').height(), // it gonna request when scroll is 10 pixels before the page ends
    'beforeLoad': function(){ // before load function, you can display a preloader div
        //$('#loading-pic').show();
        this.flagRequesting = 0;
    },
    'afterLoad': function(elementsLoaded){ // after loading content, you can use this function to animate your new elements

    //记录分页的dom数据
        for (var i = 0; i < elementsLoaded.length; i++) {
            dom += $(elementsLoaded[i]).html();
        }
        if(!!dom) History.pushState({'dom':dom,'p':this.contentData.page+1});//记录最后一次分页加载的dom数据以及下一页的起始数
        //end

        this.contentData.page++; 
         $(".test_list").append('<img src="/mobile/img/ads.jpg" class="ads_img">');

        }
    this.flagRequesting = 1;
    }
});

上面代码仅测试,需自行修改。
主要起作用的位置是 记录分页的dom数据获取缓存数据 两处注释块。
道理还是那样,只是更优化了些。这里缓存了所有ajax分页的DOM数据和请求的最后的页码,当返回到列表页面的时候获取缓存DOM并加载,起始的分页数也会还原。
history.js内部也是使用sessionstorage来缓存相关数据,所以设置state数据的时候需要将DOM对象转换为String字符串数据就可以缓存整个分页数据。
实际使用中会发现个别时候item详情页面中执行history.go(-1)或者点击A标签链接返回到列表页面的时候缓存的分页DOM数据可以正常的显示,但是滚动条定位就没达到想要的效果,所以要完美应该在获取缓存数据的时候添加一个scrollTop滚动条的复位操作,这样应该就巴适了。

嗯~~今天遇到的这个问题还好解决了,感谢开源奉献的人们。

peace~

参考:
http://www.cnblogs.com/songbyjson/p/4886615.html

五种解决方案:http://www.cnblogs.com/snandy/archive/2011/09/18/2180102.html

博客标题下面的ajax加载一句话

作者:matrix 发布时间:2015年1月12日星期一 分类:Wordpress 兼容并蓄

博客LOGO下面的一句话功能是照搬philna2主题弄的,点击一下就更新一句话的内容,是很久前的弄的小功能,现在回忆一下简单步骤。给需要的一位童鞋。

1.在wordpress主题的functions.php中添加代码

function HHTJimSay(){
    $Sentence =
    '
    11111
    22222
    33333
    44444
    ';
    $words = explode("\n", $Sentence);
    $word = $words[ mt_rand(1, count($words) - 2) ];
    echo $word;
}
function _exitajax(){
exit();
}
function Is_AjaxURL() {
    if((isset($_GET['do']) && $_GET['do'] == 'ajax') ) {
        return true;
    }else{
        return false;
    }
}
/**
 * 通过USER_Agent判断是否为机器人.
 */
function is_bot(){
    $bots = array('Google Bot1' => 'googlebot', 'Google Bot2' => 'google', 'MSN' => 'msnbot', 'Alex' => 'ia_archiver', 'Lycos' => 'lycos', 'Ask Jeeves' => 'jeeves', 'Altavista' => 'scooter', 'AllTheWeb' => 'fast-webcrawler', 'Inktomi' => 'slurp@inktomi', 'Turnitin.com' => 'turnitinbot', 'Technorati' => 'technorati', 'Yahoo' => 'yahoo', 'Findexa' => 'findexa', 'NextLinks' => 'findlinks', 'Gais' => 'gaisbo', 'WiseNut' => 'zyborg', 'WhoisSource' => 'surveybot', 'Bloglines' => 'bloglines', 'BlogSearch' => 'blogsearch', 'PubSub' => 'pubsub', 'Syndic8' => 'syndic8', 'RadioUserland' => 'userland', 'Gigabot' => 'gigabot', 'Become.com' => 'become.com','Bot'=>'bot','Spider'=>'spider','yinheli_for_test'=>'dFirefox');
    $useragent = $_SERVER['HTTP_USER_AGENT'];
    foreach ($bots as $name => $lookfor) {
        if (stristr($useragent, $lookfor) !== false) {
            return true;
            break;
        }
    }
}
if(Is_AjaxURL() && !is_bot()){//存在_GET且不是机器
add_action('Ready','HHTJimSay');
add_action('Ready', '_exitAjax', 9999);
}
do_action( 'Ready');

说明:
用于ajax后台提取一句话函数
4-7行处自己添加需要显示的一句话

2.在header.php中,加载完jq之后的位置添加js代码

var blogURL="https://www.hhtjim.com";//网站域名  
$(function(){  
    function o(v){  
        url=v.u?v.u:blogURL+"?do=ajax";  
        if(v.fn){  
            var nowTime = new Date().getTime();  
            url+="&action="+v.fn+"&t="+nowTime  
        }  
        type=v.m?v.m:"GET";  
        data=v.d?v.d:null;  
        dataType=v.dt?v.dt:"html";  
        beforeSend=v.b?v.b:null;  
        error=v.e?v.e:function(){  
            alert(lang.commonError);  
            document.body.style.cursor="auto"  
        };  
        success=v.s?v.s:function(w){  
            alert(w)  
        };  
        $.ajax({  
            url:url,type:type,data:data,dataType:dataType,beforeSend:beforeSend,error:error,success:success  
        })  
    }  

    function u(){  
        var v=false;  
        var x=document.getElementById('HHTJimSay') ? $("#HHTJimSay") : $("#HHTJimSay_s") ;  
        var w="loading";  
        x.click(function(){  
            if(v){  
                return false  
            }  
            var z=function(){  
                x.hide(0,function(){  
                    x.attr('title','').html("").addClass(w).show();//0秒后出现漏斗  

                });  
                v=true  
            };  
            var y=function(){  
                x.html(lang.commonError);  
                x.removeClass(w);  
                v=false  
            };  
            var A=function(B){  
                setTimeout(function(){  
                    x.hide(0);  
                    x.attr('title','点击这里获取更新').html(B).removeClass(w).fadeIn("slow"); //show(300)改fadeIn("slow") 淡入  
                    v=false  
                }  
                ,3000)//3000 漏斗出现时间  
            };  
            o({  
                b:z,e:y,s:A,fn:"HHTJimSay"  
            });  
            return false  
        })  
    }  
    u();  
    function n(){  
        var w=$("#welcome_msg");  
        var v=$("#profile");  
        var m=$("#author");  
        $("#edit_profile").toggle(function(){  
            w.slideUp(200);  
            v.slideDown(200);  
            m.select();  
            return false  
        }  
        ,function(){  
            w.slideDown(200);  
            v.slideUp(200);  
            return false  
        })  
    }  
    n();  
});  

说明:修改第一行的网站域名

3.在header.php处需要显示的位置添加代码

<span id="HHTJimSay_s" title="点击这里获取更新" style="white-space: nowrap;" class="description"><?php HHTJimSay(); ?></span>

4.在style.css中添加样式代码

#HHTJimSay_s{background:url('data:image/gif;base64,R0lGODlhEAAQALMJALvM7rDE6aW86UV10leF2WWM2cXj/zNmzP///////wAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAAAJACwAAAAAEAAQAAAENDDJCUoBM+tyTtGTMAgJ50mGNhxDUl2JIWciCaZgru/avPs+XZBHLOJuvSFKeQwec8oiKAIAIfkECQAACQAsAAAAABAAEAAABDcwyZlCoJiGc26WhrR1QEEAlKGKV8ERWIi5R/FhZYHefLLyv99N2CsaZRkkiLhU+iZCZ0xqxEQAACH5BAkAAAkALAAAAAAQABAAAAQ2MMlJq5XG3KlxF4NAZR01HENVUqC4vbAEFAWQZG9xHMW9VjpeLDGrDS8/jgq3/JWYNxj0eIkAACH5BAkAAAkALAAAAAAQABAAAAQ0MMlJq5XG3KlxT58XitXIbWhaBYGHBsfRZm/cqgmrAkUBlJZCrEDJjIQHAtDFI/w2NFwqAgAh+QQJAAAJACwAAAAAEAAQAAAENDDJSauVxtypcU+fF4rVyG1oimYpC5qUq84qLAxCzAJFASSDw6AkKRwOhcQtdzEiZzyfJQIAIfkECQAACQAsAAAAABAAEAAABDUwyUmrlcbcqXFPnxeK1chtaIpmKQualKtaQFEAc3EchTUSu14gQJoACLfAjghCKQ9M1fASAQAh+QQJAAAJACwAAAAAEAAQAAAENTDJSauVxtypcU+fF4rVyG2oBBQFkErFcRRolsRzra3t61+CgeAyGhwGlkwoOAR9TBTbDxUBACH5BAUAAAkALAAAAAAQABAAAAQ4MMlJq5XGXAlIAUk2aRRxHEWVkVJxpmoFFN82BYFNBWe+ibyD7yJK4HRIJCtGWVmczRFr+aQmLREAOw==') no-repeat 10000px 10000px;cursor:pointer;}
#HHTJimSay_s.loading{cursor:default;display:none;background-position:center center;width:18px;height:16px;}

IE浏览器Ajax请求时304错误

作者:matrix 发布时间:2014年4月24日星期四 分类:Wordpress

博客LOGO下面的一句话功能是按照philna2主题弄的,点击一下就更新内容。但是每次用IE浏览器点击获取都会停留在固定的一句话,F12之后才看到是304错误。客户端代码用的jq ajax()方法,理论上是支持各种浏览器的。

今天终于解决这个问题,都是狗日的IE浏览器缓存搞的。

原因:

IE浏览器ajax时会缓存之前get请求过的URL内容,如果下次还请求那个URL就从本地缓存中取出,之后也就会停止ajax请求。所以会失败,总是停留在一个请求内容里。

解决:

请求的URL地址中加上动态值,比如UNIX时间戳。

像这样的地址  http://127.0.0.1?do=ajax&t=这里为UNIX时间戳

UNIX时间戳每秒都在变化,每次请求地址的URL都不一样,IE也就缓存不到。

js代码参考:

var nowTime = new Date().getTime();

参考:

http://blog.csdn.net/puncha/article/details/17962623

ajax跨域请求json数据

作者:matrix 发布时间:2014年3月13日星期四 分类:零零星星

ajax
刚开始仅仅想获取一个他域的json数据,没想到牵扯到很多的问题。
每次都请求失败:
chrome面板的status为(canceled)

在Request Header这里显示CAUTION Provisional headers are shown

CAUTION Provisional headers are shown

 

后来才知道是ajax跨域问题导致:

也就是ajax同源策略(同源是指域名,协议,端口相同)。
跨域可以实现在自己的网站之间传递数据。但是如果你想用“跨域”盗取其它网站的数据,那还是放弃吧。除非目标网站有给你提供JSONP的接口,或者有某些可以利用的漏洞,要不然真没什么办法实现。
跨域问题的产生,最主要原因是COOKIE的安全问题。因为COOKIE是属于一个域的,如果允许跨域,客户端浏览器上储存的COOKIE就可以被它的所有者之外的程序访问到。举个例子吧,假如没有跨域问题,我现在就可以给百度发送个HTTP请求,获取你在百度上登录的用户名。或者获取SessionID,直接冒充你的帐号登录。为了避免这些问题,所以跨域访问的限制是非常有必要的。

利用jsonp跨域

跨域必须要有回调函数的接口,这里用jsonp试试 阅读剩余部分 »