zoukankan      html  css  js  c++  java
  • Ajax

    参考 : http://javascript.ruanyifeng.com/bom/ajax.html#toc6 

    javascript 高级程序设计第三版. 期待第四版啊!

    本篇主要记入一些基本和常使用到的ajax方法

    服务端是用 asp.net ashx 来接收的。

    js部分不考虑游览器兼容的问题. 

    简单的理解 , ajax就是发送http请求,而不重启或刷新页面。

    这里从发送一个ajax请求还有一个 http 头说起吧 

            var xhr = new XMLHttpRequest(); 
            xhr.open("GET", "//localhost:5715/learn/ajax/ajaxhand.ashx", true); 
            xhr.setRequestHeader("Content-Type", "application/json"); 必须在open之后才能set哦   
            xhr.setRequestHeader("customHeader", "value");
            xhr.send(null);

    整个请求都是依靠这个 XMLHttpRequest 实例对象来完成的。

    open 方法

    -参数1是请求的类型method, 比如 GET,POST,PUT,DELETE 等

    -参数2是请求的网址 

    -参数3是表示是否是一个异步请求. 

    setRequestHeader 方法 (必须在open之后才能set哦)

    请求时发送给服务端的头信息 name 和 value 

    我们可以自定义一些请求头

    send 方法

    参数1是请求时具体内容(body). 有head 就有 body嘛 , 但是GET请求就不可以有body哦,即使你放了也传不去后台。

    参数除了string 还支持 ArrayBuffer ,Blod,FormData类型等 ..之后会讲到 

    好了我们看看后台如何获取这些信息 

    <%@ WebHandler Language="C#" Class="ajaxhand" %>
    
    using System;
    using System.Web;
    using MySql.Data.MySqlClient;
    using System.Data;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Collections.Generic;
    using System.Collections;
    using System.Web.SessionState;
    using System.Linq;
    using System.Reflection;
    using System.IO;
    using System.Text;
    using stooges_funcV3;
    using System.Collections.Specialized;
    
    public class ajaxhand : IHttpHandler 
    {
        public void ProcessRequest (HttpContext context) 
        {
            //遍历header
            NameValueCollection head = context.Request.Headers;
            String[] headersKey = head.AllKeys;
            foreach (string key in headersKey)
            {
                String[] values = head.GetValues(key);
                string value = values[0]; //通常只有一个
            }          
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");       
        }
     
        public bool IsReusable {
            get {
                return false;
            }
        }
    }
    View Code

    整体大致上是这样,我们通过偏离header就可以完全获取header资料了. 

    除了header 我们还常会通过urlParams来做传信息,比如 

            var urlParams = "?" + encodeURIComponent("k ey") + "=" + encodeURIComponent("v alue"); //?a%20b=b%20c  记得要加密
            xhr.open("GET", "//localhost:5715/learn/ajax/ajaxhand.ashx" + urlParams, true);
            string value = context.Request["k ey"];
            string value2 = context.Request.QueryString["k ey"]; 
            string[] allkeys = context.Request.QueryString.AllKeys; //遍历
            foreach (string key in allkeys)
            {        
                string paravalue = context.Request.QueryString[key];
            }

    还有 cookie 

            string[] keys = context.Request.Cookies.AllKeys;
            foreach (string key in keys)
            {
                string x = context.Request.Cookies[key].Value.ToString();
            }

    到此我们先说说响应的部分了 

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 1) {
                    console.log("open"); //调用了open方法
                }
                else if (xhr.readyState == 4) { //3表示接收到了响应但是没有完成 , 4则表示响应已完成。 
                    if (xhr.status >= 200 && xhr.status <= 300 || xhr.status == 304) {                  
                        console.log(xhr.responseText); //响应的返回值
                    }
                    else {
                        console.log("ajax fail");
                    }
                }            
            }
            xhr.open("GET", "//localhost:5715/learn/ajax/ajaxhand.ashx", true);
            //xhr.setRequestHeader("Content-Type", "application/json");          
            xhr.send(null);

    监听 onreadystatechange 

    readyState 表示 xhr当前的状态 . 

    1代表open被调用了。

    3代表接收到响应了,但还不完整(可以用这个做http流,之后可能会讲到)

    4代表已经完成. 

    xhr.status 就是需要返回代号。 比如404表示找不到地址,这个熟了吧 . 

    一般200表示很好。 304 表示请求的资料本地缓存还没有过期可以直接使用。

    xhr.responseText 就是我们要的数据啦.  

            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");      

    服务端的响应大概是这样的。 

       var str = xhr.getAllResponseHeaders(); //返回的是string 要自己分析
       var value = xhr.getResponseHeader("key"); //直接取值

    前端获取响应头信息 

    上面都是在说GET,现在我们来写一个POST请求看看

    xhr.open("POST", "//localhost:5715/learn/ajax/ajaxhand.ashx", true);
    xhr.send("hello"); //纯字符串 

    服务端 :

     string method = HttpContext.Current.Request.HttpMethod; //POST
    StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8); string value = reader.ReadToEnd(); //hello

    表明contentType 是 FormData

            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); //表明是form格式
            var someData = encodeURIComponent("a b") + "=" + encodeURIComponent("b c"); //?a%20b=b%20c 要key=value 和加密哦
            xhr.send(someData);

    服务端 : 

      string value = context.Request["a b"]; //b c 一样拿的到
      string value2 = context.Request.QueryString["a b"]; //null QueryString只能拿到url的params

    服务端在获取的时候最好先判断 contentType 来决定用什么方式获取资料,比如json的话还要反序列化等等。 

    再来我们试试用表单提交 

        <form id="formId">
            <input type="text" name="name" value="keatkeat" />
            <input type="text" name="age" value="10" />     
        </form>
            //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); //不用声明了
            var formElem = document.getElementById("formId");
            var formData = new FormData(formElem); //把表单丢进去
            formData.append('csrf', 'a b c'); //扩展表单内容
            xhr.send(formData);
    关键是使用了 new FormData 
    append 方法可以添加而外的key value 给form 会自动加密
    可以看出来,这个方式取代了之前的post form 方案,这个不用写header也不用加密等,更方便了。
    服务端依据 :
            string [] keys =  context.Request.Form.AllKeys;
            foreach (string key in keys)
            {
                var value = context.Request.Form[key];
            }

    现在我们来试试上传文件

                xhr.upload.onprogress = function (e) {
                    if (e.lengthComputable) {
                        var percentComplete = e.loaded / e.total; //百分比                   
                    }
                }
                xhr.upload.onload = function () {
                    console.log("done upload");
                }

    首先是监听上传的进度 

           <input id="fileId" type="file" multiple="multiple" />
    
                var formData = new FormData(); //把表单丢进去
                var fileElem = document.getElementById("fileId");
                var files = fileElem.files;
                for (var i = 0; i < files.length; i++) {
                    var file = files[i];
                    formData.append("file" + i, file);
                }
                xhr.send(formData);

    一个上传控件 , 这里是支持多文件上传的 . 

    这里我们循环formData.append(fileName,file); 是因为一个控件只有一个name 但是我们却是 multiple files ,这样在服务端不好区分开来。

    服务端很简单 : 

            string[] keys = context.Request.Files.AllKeys;
            foreach (string key in keys) //key 就是我们循环取的name
            {
                HttpPostedFile file = context.Request.Files[key];
                file.SaveAs(context.Server.MapPath(@"~\image.png")); //直接保存
            }

     此外我们还可以中断请求 

            xhr.onabort = function () {
                    alert("aboat");
                }
                xhr.send("str");
                setTimeout(function () {
                    xhr.abort();
                }, 1);

    通过 abort 方法来中断,也可以监听

    再来我们看看 ajax 如何跨域请求. 

    基本上js是不用去管请求是否是跨域的。游览器会帮我做好。除了IE (低版本8,9)

    那么主要是服务端要设置一下。 

    一个跨域的http 请求会附带一个header   key = Origin , value = '地址'

            String[] origin = context.Request.Headers.GetValues("Origin"); //跨域的http请求会带着个header
            if (origin != null) 
            {
                string requestFromUrl = origin[0]; //装原来的url 
                //验证一下决定要不要运行它访问
                if (true)
                {
                    context.Response.AddHeader("Access-Control-Allow-Origin", requestFromUrl); //把url设定进去就可以了               
                }
                else
                {
                    context.Response.Write("fail");   
                }            
            }

    发现是跨域情况,我们看看它的地址,是那个网站来的等等,判断是否要让它请求。 

    响应一个 header Access-Control-Allow-Origin , 来访的地址就可以了。

    更新 : 2016-02-28 

    url  : "/api/products" = "http://www.stooges.com.my/api/products" (domain + /api/products)

    url  : "api/products" = "http://www.stooges.com.my/Home/api/products" (currentpage + /api/products)

    url : "../api/products" = /api/products (../ 在这里是不管用的)

  • 相关阅读:
    rails路由
    RRD.so文件 rrdruby
    windows rails new demo时候出错Make sure that `gem install mysql2 -v '0.3.15'` succeeds before bundling.
    d3js把circle和rect连接在一起
    ubuntu 12.04 rails server 时候报错 execjs
    mysql2
    rails rake 版本问题
    rails下mysql出错问题mysql_api,blog/text
    ubuntu安装mysql
    vmware下ubuntu不能上网 => 恢复默认虚拟网络
  • 原文地址:https://www.cnblogs.com/keatkeat/p/3957130.html
Copyright © 2011-2022 走看看