拦截所有AJAX调用,重点处理服务器异常

背景

上篇文章http://www.cnblogs.com/happyframework/p/3241063.html介绍了如何以AOP的形式处理服务器异常,这让服务器端的编程逻辑变的非常整洁,本文介绍如何在客户端统一处理服务器返回的异常信息。

一点考虑

上篇隐藏了一些概念,即:开发或架构之处,就应当确定哪些异常要返回给UI、哪些异常要写入日志、哪些异常要包装以后返回给UI等等。

AJAX拦截

如何拦截AJAX,不外乎这三种方式:

  1. 注册全局监听函数。
  2. 封装一个全局入口。
  3. 重写或覆盖客户端库的AJAX功能(Javascript是动态语言,可以运行时替换任何东西)。

最简单的莫过于第一种方式,让我们看一下代码:

拦截事件

 1 /// <reference path="/ext/ext-all-debug-w-comments.js" />
2 Ext.define('Tenoner.AjaxMonitor', {
3 singleton: true,
4 requires: ['Ext.Ajax'],
5
6 errorHandlers: [],
7
8 constructor: function () {
9 var me = this;
10
11 Ext.Ajax.timeout = 120000;
12
13 Ext.Ajax.on('requestcomplete', function (connection, response, option) {
14 me.processError(response);
15 });
16
17 me.callParent(arguments);
18 },
19
20 addErrorHandler: function (errorHandler) {
21 var me = this;
22
23 me.errorHandlers.push(errorHandler);
24 },
25
26 processError: function (response) {
27 var me = this;
28
29 var result = Ext.decode(response.responseText);
30
31 if (!result || !result.errorCode) {
32 return;
33 }
34
35 Ext.Array.each(me.errorHandlers, function (errorHandler) {
36 Ext.Object.each(errorHandler, function (errorCode, handler) {
37 if (errorCode == result.errorCode) {
38 handler();
39 }
40 });
41 });
42 }
43 });

注册一个异常拦截方法

 1         Tenoner.AjaxMonitor.addErrorHandler({
2 'CM001': function () {
3 var current = window;
4
5 while (current != current.parent) {
6 current = current.parent;
7 }
8
9 current.location.href = '/Login.htm';
10 }
11 });

我们还能做哪些?

如果希望自动弹出错误提示,也可以以这种形式处理,这样Javascript代码中也尽可能的是正常的代码。

备注

本文以ExtJs为例,不过思路应当适合所有AJAX框架。

瀑布流效果目前应用很广泛,像花瓣,新浪轻博,蘑菇街,美丽说等好多网站都有.也有好多支持该效果的前段框架,今天学习了一下这种效果的实现,不依赖插件,自己动手分析实现过程,为了便于叙述清楚,分析中的一些名词为自己拟定,不当之处还望见谅.

思路分析

步骤一:构建成行元素 + 寻找新增元素追加位置

瀑布流所有元素的宽度是固定的,我们用浏览器的宽度除以每个瀑布流块的宽度,就是每一行可容纳的瀑布流块的个数.因为,每个瀑布流块的高度不一,我们姑且把组成一行的这组元素称为成行元素,在成行元素放置完毕后,我们如果要再增加一个元素,那么它的位置应该这样找?

“获取成行元素集合中高度最低的那个元素,待放置的元素的top值应该是这个最低元素的高,left值应该是这个最低元素的left值”

这样,新增的这一个元素我们就找到了它存放的位置.这样成行元素中的最低高度值就变为了原来的高度+新增元素的高度.

步骤二:重复步骤一,依赖成行元素追加新元素

步骤一中我们已经实现了一次成行元素追加一个新的元素,这样新元素增加之后我们就构建了新的成行元素,之后的操作就是在新的成行元素中追加新元素,原理同步骤一.

步骤三:实现滚动位置监听,到底部时加载数据

代码实现

实现步骤一描述效果:

实现代码

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>瀑布流效果实现</title>
<script type="text/javascript" src="scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="scripts/jquery.easydrag.handler.beta2.js"></script>
<script type="text/javascript">
window.onload=function(){
//获取父级对象
var oParent = document.getElementById("main");
//获取父级[第一个参数]下的所有的子元素[按照第二个参数匹配]
var aPin = getClassObject(oParent,"pin");
//获取每一个块的宽度
var iPinW = aPin[0].offsetWidth;
// //计算每行放多少个pin(瀑布流块)页面的宽度/每一个瀑布流块的宽度
var num = Math.floor(document.documentElement.clientWidth/iPinW);
//重置父级的样式,这样保证图片整体居中
oParent.style.cssText="width:" + num*iPinW + "px;margin:0 auto;"; var compareArray = [];
//将一整行的瀑布流块的高度压入一个数组
for (var i = 0; i<num; i++) {
compareArray[i] = aPin[i].offsetHeight;
} //获取该行瀑布流高度最低的值
var minHeight = Math.min.apply('',compareArray);
//alert(compareArray + ",min=" + minHeight);
//获取改行高度值最小的瀑布流块的索引
var minHkey = getMinHeightKey(compareArray,minHeight); //为新增的瀑布流块增加样式
aPin[num].style.position = "absolute";
aPin[num].style.top = minHeight + "px";
//设定新增加的瀑布流块的top和left
aPin[num].style.left =aPin[minHkey].offsetLeft + "px"; //将该索引位置的高度改变为新增后的高度[原来瀑布流块的高度+新增的瀑布流块的高度]
compareArray[minHkey] += aPin[num].offsetHeight; }
/**
* 获取parent下所有样式名为className的对象集合
*/
function getClassObject(parent,className){
var obj = parent.getElementsByTagName("*");
var result = [];
for(var i=0; i<obj.length;i++){
//变量如果匹配className,将匹配的对象放入数组
if(obj[i].className==className){
result.push(obj[i]);
}
}
return result;
} /**
* 获取arr数组中值为minH的值在数组中的索引
*/
function getMinHeightKey(arr,minH){
for(key in arr){
if(arr[key] == minH){
return key;
}
}
}
</script>
<style type="text/css">
/*设置每一个瀑布流块*/
#main .pin{
width:220px;
height: auto;
padding: 15px 0px 0px 15px; /*上 右 下 左*/
float: left;
}
/*设置每一个瀑布流块中的图像样式*/
#main .pin .box{
width: 200px;
height: auto;
padding: 10px;
background: #FFF;
border: 1px solid #ccc;
box-shadow: 0px 0px 6px #ccc; /*中间投影*/
border-radius: 5px; /*圆角*/
}
#main .pin .box img{
width: 200px; }
</style>
</head>
<body>
<div id="main">
<!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012110120000859759.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012072300483800466.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012101912011350194.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012102421195356552.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012072312335411883.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012082910221472225.jpg">
</div>
</div> </div>
</body>
</html>

实现步骤二描述效果

实现代码

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>瀑布流效果实现</title>
<script type="text/javascript" src="scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="scripts/jquery.easydrag.handler.beta2.js"></script>
<script type="text/javascript">
window.onload=function(){
//获取父级对象
var oParent = document.getElementById("main");
//获取父级[第一个参数]下的所有的子元素[按照第二个参数匹配]
var aPin = getClassObject(oParent,"pin");
//获取每一个块的宽度
var iPinW = aPin[0].offsetWidth;
// //计算每行放多少个pin(瀑布流块)页面的宽度/每一个瀑布流块的宽度
var num = Math.floor(document.documentElement.clientWidth/iPinW);
//重置父级的样式,这样保证图片整体居中
oParent.style.cssText="width:" + num*iPinW + "px;margin:0 auto;"; var compareArray = [];
//遍历获取到的所有瀑布流块
for (var i = 0; i<aPin.length; i++) {
if(i<num){
//成行元素
compareArray[i] = aPin[i].offsetHeight;
}else{
//获取成行元素中高度最低的值
var minHeight = Math.min.apply('',compareArray);
//alert(compareArray + ",min=" + minHeight);
//获取成行元素中高度最低元素的索引
var minHkey = getMinHeightKey(compareArray,minHeight);
//为新增的瀑布流块设置定位
aPin[i].style.position = "absolute";
aPin[i].style.top = minHeight + "px";
//设定新增加的瀑布流块的top和left
aPin[i].style.left =aPin[minHkey].offsetLeft + "px";
//将该索引位置的高度改变为新增后的高度[原来瀑布流块的高度+新增的瀑布流块的高度]
compareArray[minHkey] += aPin[i].offsetHeight;
} } }
/**
* 获取parent下所有样式名为className的对象集合
*/
function getClassObject(parent,className){
var obj = parent.getElementsByTagName("*");
var result = [];
for(var i=0; i<obj.length;i++){
//变量如果匹配className,将匹配的对象放入数组
if(obj[i].className==className){
result.push(obj[i]);
}
}
return result;
} /**
* 获取arr数组中值为minH的值在数组中的索引
*/
function getMinHeightKey(arr,minH){
for(key in arr){
if(arr[key] == minH){
return key;
}
}
}
</script>
<style type="text/css">
/*设置每一个瀑布流块*/
#main .pin{
width:220px;
height: auto;
padding: 15px 0px 0px 15px; /*上 右 下 左*/
float: left;
}
/*设置每一个瀑布流块中的图像样式*/
#main .pin .box{
width: 200px;
height: auto;
padding: 10px;
background: #FFF;
border: 1px solid #ccc;
box-shadow: 0px 0px 6px #ccc; /*中间投影*/
border-radius: 5px; /*圆角*/
}
#main .pin .box img{
width: 200px; }
</style>
</head>
<body>
<div id="main">
<!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012110120000859759.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012072300483800466.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012101912011350194.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012102421195356552.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012072312335411883.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012082910221472225.jpg">
</div>
</div> <!--每一个小块-->
<div class="pin">
<div class="box">
<img src="data:images/2012082910024626515.jpg">
</div>
</div> </div>
</body>
</html>

会看到新增的瀑布流块在新的成行元素中自动寻找高度最低的那个元素块的相对位置进行追加.添加更多元素查看效果

步骤三:实现滚动到底部时加载数据
该部分没有什么功能,只是检测滚动条的位置距离浏览器底部的相对距离进行数据加载,加载数据时创建对应的瀑布流块.判断相对距离的实现逻辑如下

        function checkScrollSite(){
var oParent = document.getElementById("main"); var aPin = getClassObject(oParent,"pin");
//加载数据依赖最后一个瀑布流块变化
var lastPinHeight = aPin[aPin.length-1].offsetTop + Math.floor(aPin[aPin.length-1].offsetHeight/2) ;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
//浏览器高度
var documentH = document.documentElement.clientHeight; if(lastPinHeight<documentH + scrollTop){
//请求数据
return true;
}
return false;
}

在此感谢,郑印在学习上给予的指导.

转载请注明出处:[http://www.cnblogs.com/dennisit/p/3244987.html]

web前端学习笔记-瀑布流的算法分析与代码实现

热爱生活,热爱Coding,敢于挑战,用于探索 ...
 
分类: JavaEEWeb前端
标签: 瀑布流

拦截所有AJAX调用,重点处理服务器异常的更多相关文章

  1. Javascript:拦截所有AJAX调用,重点处理服务器异常

    背景 上篇文章http://www.cnblogs.com/happyframework/p/3241063.html介绍了如何以AOP的形式处理服务器异常,这让服务器端的编程逻辑变的非常整洁,本文介 ...

  2. C# 调用Excel 出现服务器出现意外情况. (异常来自 HRESULT:0x80010105 (RPC_E_SERVERFAULT)

    C# 调用Excel 出现服务器出现意外情况. (异常来自 HRESULT:0x80010105 (RPC_E_SERVERFAULT) private Microsoft.Office.Intero ...

  3. 最新升级的火狐38.0.6识别ajax调用返回的""空值可能有异常。

    自已在调用一段ajax开发中,返回的是空值 string result = string.Empty;return result; 但在页面进行$.ajax调用 时 输出alert(result);应 ...

  4. Jquery Ajax调用aspx页面方法

    Jquery Ajax调用aspx页面方法 在asp.net webform开发中,用jQuery ajax传值一般有几种玩法 1)普通玩法:通过一般处理程序ashx进行处理: 2)高级玩法:通过as ...

  5. 使用JQuery的Ajax调用SOAP-XML Web Services(Call SOAP-XML Web Services With jQuery Ajax)(译+摘录)

    假设有一个基于.Net的Web Service,其名称为SaveProduct POST /ProductService.asmx HTTP/1.1 Host: localhost Content-T ...

  6. jquery.ajax请求aspx和ashx的异同 Jquery Ajax调用aspx页面方法

    1.jquery.ajax请求aspx 请求aspx的静态方法要注意一下问题: (1)aspx的后台方法必须静态,而且添加webmethod特性 (2)在ajax方法中contentType必须是“a ...

  7. ASP.NET实现二维码 ASP.Net上传文件 SQL基础语法 C# 动态创建数据库三(MySQL) Net Core 实现谷歌翻译ApI 免费版 C#发布和调试WebService ajax调用WebService实现数据库操作 C# 实体类转json数据过滤掉字段为null的字段

    ASP.NET实现二维码 using System;using System.Collections.Generic;using System.Drawing;using System.Linq;us ...

  8. Ajax调用处理页面错误信息500的解决思路

    最近在做项目的时候遇到一个问题:(李昌辉) 在本地服务器上做好之后,部署到阿里云虚拟主机,结果访问页面出现问题,由于登录使用的是AJAX调用处理页面,所以在点击登录的时候没有任何反应. 打开F12调试 ...

  9. 使AJAX调用尽可能利用缓存特性

    优化网站设计(十四):使AJAX调用尽可能利用缓存特性 前言 网站设计的优化是一个很大的话题,有一些通用的原则,也有针对不同开发平台的一些建议.这方面的研究一直没有停止过,我在不同的场合也分享过这样的 ...

随机推荐

  1. ThinkPHP 3.2 开放 cache注缓存,过滤非法字符

    打开缓存配置文件 /Application/Common/conf/cache.php源代码如下面: <?php return array( //'配置项'=>'配置值' 'LAYOUT_ ...

  2. PyCharm 使用简介

    PyCharm 使用简介 最近由于项目需要,领导要求使用python以方便扩展,没有办法,赶鸭子上架花了2天时间翻完了python的初级教程然后就开始写代码.有一款好的IDE可以帮助我快速上手一门新语 ...

  3. javascript如何解析json对javascript如何解析json对象并动态赋值到select列表象并动态赋值到select列表

    原文 javascript如何解析json对象并动态赋值到select列表 JSON(JavaScriptObject Notation)一种简单的数据格式,比xml更轻巧.JSON是JavaScri ...

  4. TML5安全:CORS(跨域资源共享)简介

    来源:http://blog.csdn.net/hfahe/article/details/7730944 前言:像CORS对于现代前端这么重要的技术在国内基本上居然很少有人使用和提及,在百度或者Go ...

  5. POJ 3928 &amp; HDU 2492 Ping pong(树阵评价倒数)

    主题链接: PKU:http://poj.org/problem?id=3928 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Descript ...

  6. JS模板引擎:tppl

    全球最快的JS模板引擎:tppl 废话不多说,先上测试: 亲测请访问:[在线测试地址]单次结果不一定准确,请多测几次. tppl 的编译渲染速度是著名的 jQuery 作者 John Resig 开发 ...

  7. 清空SQL Server数据库中所有表数据的方法

    原文:清空SQL Server数据库中所有表数据的方法 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间可能形成相互约束关系,删除操作可 ...

  8. 单独一个img标签的居中显示

    针对页面当中通过img插入图片的时候,要保证这个图片在页面内容当中居中,一般的做法是在外面套一个div,通过给div加入 {margin:0 auto;} 来控制图片的居中. 那么如果针对后台上传的图 ...

  9. TodoList开发笔记 – PartⅠ

    做了一年多的桌面软件,最近开始转向Web方面的开发,既然比较熟悉Net那么首当其冲就是学习ASP.Net,以及HTML.CSS.Javascript. 为了检验这个把星期来的学习成果,着手做了一个To ...

  10. ajax的post请求

    get和post是http请求方法最主要的两种方式. post: 来个例子test.html <!doctype html> <html lang="en"> ...