JavaScript学习总结——延迟对象跨域模板引擎弹出层AJAX示例

Posted 风花雪月华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript学习总结——延迟对象跨域模板引擎弹出层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">
           /*callback是一个当ajax请求成功时的回调方法*/
            function getStudent(callback) {
                $.get("student.json", function(data) {
                    callback(data);
                }, "json");
            }
            
            /*调用getStudent函数,传入参数,参数也是一个函数*/
            getStudent(function(stu){
                alert(stu.id);
            });
            
            /*把一个方法作为参数传递给另一个方法可以认为是委托,如C++中的函数指针类似*/
            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执行使用参数提供给 resolveresolveWith方法依照添加的顺序调用。

示例代码:

复制代码
<!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执行使用参数提供给 resolveresolveWith方法依照添加的顺序调用。

示例:

复制代码
<!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>
        <

以上是关于JavaScript学习总结——延迟对象跨域模板引擎弹出层AJAX示例的主要内容,如果未能解决你的问题,请参考以下文章

WEB前端开发需要学习什么知识(上)

JavaScript学习--Item33 跨域总结与解决办法

JavaScript学习总结 Ajax和Http状态字

前端面试知识点锦集(JavaScript篇)

Javascript Ajax总结——跨域资源共享

你不知道的JavaScript--Item33 跨域总结与解决办法