详解js的延迟对象、跨域、模板引擎、弹出层、AJAX【附实例下载】

时间:2021-05-25

目录

一、AJAX示例

1.1、优点

1.2、缺点

1.3、jQuery AJAX示例

二、延迟对象(Deferred)

2.1、回调函数

2.2、deferred.done

三、跨域

3.1、什么是跨域

3.2、JSONP跨域

3.3、jQuery使用JSONP跨域

3.4、跨域资源共享(CORS)

3.5、小结

四、弹出层

五、模板引擎

  • 5.1、Hello World
  • 5.2、方法
  • 5.3、与AJAX结合应用

六、示例下载

一、AJAX示例

AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML) 是指一种创建交互式网页应用的开发技术、改善用户体验,实现无刷新效果。

1.1、优点

不需要插件支持

优秀的用户体验

提高Web程序的性能

减轻服务器和带宽的负担

1.2、缺点

浏览器对XMLHttpRequest对象的支持度不足,几乎所有浏览器现在都支持

破坏浏览器“前进”、“后退”按钮的正常功能,可以通过简单的插件弥补

对搜索引擎的支持不足

1.3、jQuery AJAX示例

在HTML5中对原生的AJAX核心对象XMLHttpRequest进行升级,也就是XHR2,功能更加强大。

jQuery对AJAX封装的非常好,这里以简单的商品管理为示例使用jQuery完成AJAX应用。

Product.java bean:

package com.gomall.bean;/*** * 产品 * * @author Administrator * */public class Product { /** 编号 */ private int id; /** 名称 */ private String name; /** 价格 */ private double price; /** 图片 */ private String picture; /** 详细 */ private String detail; @Override public String toString() { return "Product [id=" + id + ", name=" + name + ", price=" + price + ", picture=" + picture + ", detail=" + detail + "]"; } public Product(int id, String name, double price, String picture) { super(); this.id = id; this.name = name; this.price = price; this.picture = picture; } public Product(int id, String name, double price, String picture, String detail) { super(); this.id = id; this.name = name; this.price = price; this.picture = picture; this.detail = detail; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getPicture() { return picture; } public void setPicture(String picture) { this.picture = picture; } public String getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; }}

IProductService.java:

package com.gomall.service;import java.util.List;import com.gomall.bean.Product;public interface IProductService { /**获得所有*/ List<Product> getAll(); /**添加 * @return */ boolean add(Product entity); /**根据编号获得产品对象*/ Product findById(int id); /**根据编号获得产品对象 * @return */ boolean deleteById(int id);}

ProductService.java:

package com.gomall.service;import java.util.ArrayList;import java.util.List;import java.util.Random;import com.gomall.bean.Product;public class ProductService implements IProductService { public static ArrayList<Product> products; static { products = new ArrayList<>(); Random random = new Random(); for (int i = 1; i <= 10; i++) { Product product = new Product(i, "华为Mate9MHA-AL00/4GB RAM/全网通华为超级闪充技术双后摄设计" + random.nextInt(999), random.nextDouble() * 1000, "pic(" + i + ").jpg", "产品详细"); products.add(product); } } /* * (non-Javadoc) * * @see com.gomall.service.IProductService#getAll() */ @Override public List<Product> getAll() { return products; } /* * (non-Javadoc) * * @see com.gomall.service.IProductService#add(com.gomall.bean.Product) */ @Override public boolean add(Product entity) { try { entity.setId(products.size() + 1); entity.setPicture("pic(" + entity.getId() + ").jpg"); // uploadify // 上传图片 products.add(entity); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /* * (non-Javadoc) * * @see com.gomall.service.IProductService#findById(int) */ @Override public Product findById(int id) { for (Product product : products) { if (product.getId() == id) { return product; } } return null; } /* * (non-Javadoc) * * @see com.gomall.service.IProductService#deleteById(int) */ @Override public boolean deleteById(int id) { try { Product product = findById(id); if (product != null) { products.remove(product); } } catch (Exception e) { e.printStackTrace(); return false; } return true; }}

ProductAction.java:

package com.gomall.action;import java.io.IOException;import java.io.PrintWriter;import java.util.Date;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.codehaus.jackson.map.ObjectMapper;import com.gomall.bean.Product;import com.gomall.service.IProductService;import com.gomall.service.ProductService;@WebServlet("/Product")public class ProductAction extends HttpServlet { private static final long serialVersionUID = 1L; public ProductAction() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); String act = request.getParameter("act"); IProductService productService = new ProductService(); /**用于序列化json*/ ObjectMapper mapper = new ObjectMapper(); PrintWriter out=response.getWriter(); if (act.equals("getAll")) { String json = mapper.writeValueAsString(productService.getAll()); out.append(json); } else if (act.equals("area")) { String callback=request.getParameter("callback"); out.append(callback+"('"+new Date()+"')"); } else if (act.equals("getJSONP")) { String callback=request.getParameter("callback"); String json = mapper.writeValueAsString(productService.getAll()); out.append(callback+"("+json+")"); } else if (act.equals("getAllCORS")) { /**向响应的头部中添加CORS信息*/ response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET,POST"); String json = mapper.writeValueAsString(productService.getAll()); out.append(json); } else if(act.equals("del")){ /**向响应的头部中添加CORS信息*/ response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET,POST"); int id=Integer.parseInt(request.getParameter("id")); String json = mapper.writeValueAsString(productService.deleteById(id)); out.append(json); } else if(act.equals("add")){ /**向响应的头部中添加CORS信息*/ response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET,POST"); String name=request.getParameter("name"); double price=Double.parseDouble(request.getParameter("price")); String detail=request.getParameter("detail"); Product entity=new Product(0, name, price, "",detail); String json = mapper.writeValueAsString(productService.add(entity)); out.append(json); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}

运行结果:

删除:

二、延迟对象(Deferred)

deferred对象就是jQuery1.5版以后新增加的回调函数解决方案。

2.1、回调函数

先看一个示例:

首先,为什么要使用Deferred?

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>回调</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> var student; $.get("student.json",function(data){ student=data; },"json"); alert(student); </script> </body></html>

student.json文件:{"name":"tom","id":"01"}

运行结果:

因为AJAX是异步执行的,类似高级语言中的多线程,当发起ajax请求时会有网络延迟,而代码并没有在$.get的位置被阻塞,alert先执行,但数据并没有从远程获取到,所以结果是undefined。

其实初学者经常会犯这种错误,如:

function getStudentById(id){ $.get("students.do",{"id":id},function(stu){ return stu; },"json"); }

上面的代码是有问题的,原因如前面的示例是一样的。怎么解决,如果你认为是异步带来的问题,当然通过同步是可以解决的,如:

$.ajax({ type:"get", url:"student.json", async:false, success:function(data){ student=data; } });

结果:

如果将所有的ajax请求修改为同步的,则ajax的好处就大打折扣了,如果即要异步又要解决上面的问题,可以使用回调方法。

示例:

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>回调</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> function getStudent(callback) { $.get("student.json", function(data) { callback(data); }, "json"); } getStudent(function(stu){ alert(stu.id); }); getStudent(function(stu){ alert(stu.name); }); </script> </body></html>

结果:

从这里看回调很完美,其实不然,实际开发中要复杂得多,如当第一个ajax请求完成才可以完成第二个,当第二个完成才可以完成第三个,可能最一个请求要等前面的所有请求都成功时才允许执行或才有条件执行,如

使用ajax编辑用户信息,先加载用户对象,再加载省,加载市,加县,可能代码会这样写:

$.get("url1",function(){ $.get("url2",function(){ $.get("url3",function(){ ... }); }); });

当回调越来越多,嵌套越深,代码可读性就会越来越差。如果注册了多个回调,那更是一场噩梦,幸好从jQuery1.5开始出现了延迟对象(deferred),可以解决这个问题。

2.2、deferred.done

$.ajax()操作完成后,如果使用的是低于1.5.0版本的jQuery,返回的是XHR对象,你没法进行链式操作;如果高于1.5版,返回的是deferred对象,可以进行链式操作。

当延迟成功时调用一个函数或者数组函数,功能与原success类似。

语法:deferred.done(doneCallbacks[,doneCallbacks])

返回值:Deferred Object

该参数可以是一个函数或一个函数的数组。当延迟成功时,doneCallbacks被调用。回调执行是依照他们添加的顺序。一旦deferred.done()返回延迟对象,延迟对象的其它方法也可以链接到了这里,包括增加.done()方法。当延迟解决,doneCallbacks执行使用参数提供给 resolve或 resolveWith方法依照添加的顺序调用。

示例代码:

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>延迟对象(deferred)</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> console.log("使用方法一"); $.get("student.json", "json").done(function(stu) { console.log(stu.id); }).done(function(stu) { console.log(stu.name); }); console.log("使用方法二"); $.get("student.json", "json").done(function(stu) { console.log(stu.id); }, function(stu) { console.log(stu.name); }); </script> </body></html>

运行结果:

2.3、deferred.fail

语法:deferred.fail(failCallbacks[,failCallbacks])

返回值:Deferred Object

当延迟失败时调用一个函数或者数组函数,功能与原回调方法error类似。

该参数可以是一个函数或一个函数的数组。当延迟失败时,doneCallbacks被调用。回调执行是依照他们添加的顺序。一旦deferred.fail()返回延迟对象,延迟对象的其它方法也可以链接到了这里,包括增加.done()方法。当延迟解决,doneCallbacks执行使用参数提供给 resolve或 resolveWith方法依照添加的顺序调用。

示例:

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>延迟对象(deferred)</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> $.get("stu.json", "json").done(function(stu) { console.log(stu.name); }).fail(function(xhr, status, errorThrown){ alert("xhr:"+xhr+",status:"+status+",errorThrown:"+errorThrown); }); </script> </body></html>

运行结果:

2.4、deferred.always

语法:deferred.always(alwaysCallbacks,[alwaysCallbacks])

返回值:Deferred Object

当递延对象是解决(成功,resolved)或拒绝(失败,rejected)时被调用添加处理程序,与回调方法complete类似。

示例:

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>延迟对象(deferred)</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> $.get("student.j", "json").done(function(stu) { console.log(stu.name); }).fail(function(data, status, errorThrown){ console.log("data:"+data+",status:"+status+",errorThrown:"+errorThrown); }).always(function(data, textStatus){ console.log("ajax执行完成,完成状态:"+textStatus); }); </script> </body></html>

运行结果

成功时:

失败时:

2.5、deferred.then

deferred.then(doneFilter [, failFilter ] [, progressFilter ])

添加处理程序被调用时,递延对象得到解决或者拒绝,一次指定多个事件。

所有三个参数(包括progressCallbacks ,在jQuery的1.7 )可以是一个单独的函数或一个函数的数组。 其中一个参数,也可以为空,如果没有该类型的回调是需要的。或者,使用.done()或.fail()仅设置doneCallbacks或failCallbacks。当递延解决,doneCallbacks被调用。若递延代替拒绝,failCallbacks被调用。回调按他们添加的顺序执行。一旦deferred.then返回延迟对象,延迟对象的其它方法也可以链接到了这里,包括增加.then()方法。

示例:

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>延迟对象(deferred)</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> $.get("student.jsonx", "json").then(function(stu) { console.log(stu.name); }, function(data, status, errorThrown) { console.log("data:" + data + ",status:" + status + ",errorThrown:" + errorThrown); }); </script> </body></html>

结果:

2.6、应用延迟对象

前面的示例中我们都是使用jQuery ajax返回的deferred对象,其实我们也可以在自定义的代码中使用deferred对象,恰当的使用deferred对象或以优雅的解决不少问题。

示例:

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>延迟对象(deferred)</title> </head> <body> <script src="js/jQuery1.11.3/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> var myTask=function(){ //通过jQuery创建一个延迟对象 var def=$.Deferred(); setTimeout(function(){ //随机产生一个整数,如果是偶数 var n=Math.round(Math.random()*100); if(n%2==0) { console.log("一个耗时的操作终于完成了,n="+n); def.resolve(); //任务成功完成 }else{ console.log("一个耗时的操作失败,n="+n); def.reject(); //拒绝,失败 } },3000); //返回延迟对象,防止中间修改 return def.promise(); } $.when(myTask()).done(function(){ console.log("执行成功"); }).fail(function(){ console.log("执行失败"); }); </script> </body></html>

失败时:

成功时:

promise()在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。

2.7、总结

(1) 生成一个对象。  

  • 指定操作成功时的回调函数  
  • 指定操作失败时的回调函数  
  • 没有参数时,返回一个新的对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署接口。  
  • 手动改变对象的运行状态为已完成,从而立即触发方法。  
  • 这个方法与正好相反,调用后将对象的运行状态变为已失败,从而立即触发方法。  
  • .Deferred()生成一个deferred对象。  

(2)deferred.done()指定操作成功时的回调函数  

(3)deferred.fail()指定操作失败时的回调函数  

(4)deferred.promise()没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。  

(5)deferred.resolve()手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。  

(6)deferred.reject()这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。  

(7).when() 为多个操作指定回调函数。
除了这些方法以外,deferred对象还有二个重要方法,上面的教程中没有涉及到。

(8)deferred.then()
有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。

(9)deferred.always()
这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。

三、跨域

互联网上的主机由IP来标识,为了方便记忆,创建了域名系统.域名与IP对应,域名的作用是不用让你记复杂的IP地址,能唯一定位资源,URL的格式是协议://主机名.公司名称.机构类型.地域类型:端口/路径,如http://plete: app.clearMsg, error: function(xhr, textStatus, errorThrown) { app.log("错误" + textStatus + errorThrown); } }); //为模板引擎定义辅助函数 template.helper("round",function(value,mark){ return (mark||"")+Math.round(value); }); this.loadAll(); }, clearMsg: function() { this.box.remove(); }, ajaxBefore: function() { this.box = dialog({ modal: true }); this.box.show(); }, log: function(msg) { $("#message").html(msg); } }; app.init(); </script> </body></html>

运行结果:

六、示例下载

coding: http://xiazai.jb51.net/201612/yuanma/zhangguo5-javascript001-master_jb51.rar

服务器: http://xiazai.jb51.net/201612/yuanma/zhangguo5-javascript001_java-master_jb51.rar

github: http://xiazai.jb51.net/201612/yuanma/javascript01-master_jb51.rar

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章