逐步了解Ajax和Promise

简介: 逐步了解Ajax和Promise

逐步了解Ajax和Promise


Ajax

AJAX 就是用 JS 发送请求和接收响应

AJAX 是异步的 JS 和 XML(Asynchronous JavaScript And XML),目前我们一般使用 JSON 代替 XML。AJAX 主要用于在不刷新页面的情况下向浏览器发起请求并接受响应,最后局部更新页面,它最核心的概念是 XMLHttpRequest 对象,该对象可以发起 HTTP 请求,我们可以监听其 readyState 的变化获得响应。

你可以使用AJAX最主要的两个特性做下列事:

  • 在不重新加载页面的情况下发送请求给服务器。
  • 接受并使用从服务器发来的数据。

JS 中发送一个请求到成功得到响应的时间在几百毫秒到一两秒之间。

使用 AJAX 的四个步骤:

1.  创建 XMLHttpRequest 对象

通过XMLHttpRequest() 构造函数用于初始化一个 XMLHttpRequest 实例对象

var xhr = new XMLHttpRequest()

2.与服务器建立连接 调用对象的 open 方法 .open(method, url)

通过 XMLHttpRequest 对象的 open() 方法与服务器建立连接

xhr.open(method, url, [async][, user][, password])

参数说明:

  • method:表示当前的请求方式,常见的有GETPOST
  • url:服务端地址
  • async:布尔值,表示是否异步执行操作,默认为true
  • user: 可选的用户名用于认证用途;默认为`null
  • password: 可选的密码用于认证用途,默认为`null

3.  监听对象的 onreadystatechange 事件(在事件处理函数里操作 CSS / JS / HTML / responseXML / JSON.parse)

onreadystatechange 事件用于监听服务器端的通信状态,主要监听的属性为XMLHttpRequest.readyState ,

关于XMLHttpRequest.readyState属性有五个状态,如下图显示

网络异常,图片无法展示
|

只要 readyState属性值一变化,就会触发一次 readystatechange 事件

XMLHttpRequest.responseText属性用于接收服务器端的响应结果

举个例子:

const request = new XMLHttpRequest()
request.onreadystatechange = function(e){
    if(request.readyState === 4){ // 整个请求过程完毕
        if(request.status >= 200 && request.status <= 300){
            console.log(request.responseText) // 服务端返回的结果
        }else if(request.status >=400){
            console.log("错误信息:" + request.status)
        }
    }
}
request.open('POST','http://xxxx')
request.send()

4.  调用对象的 send 方法(发送请求)

通过 XMLHttpRequest 对象的 send() 方法,将客户端页面的数据发送给服务端

xhr.send([body])

body: 在 XHR 请求中要发送的数据体,如果不传递数据则为 null

如果使用GET请求发送数据的时候,需要注意如下:

  • 将请求数据添加到open()方法中的url地址中
  • 发送请求数据中的send()方法中参数设置为null
const ajax = (method, url, data, success, fail) => {
  var request = new XMLHttpRequest()
  request.open(method, url);
  request.onreadystatechange = function () {
    if(request.readyState === 4) {
      if(request.status >= 200 && request.status < 300 || request.status === 304) {
        success(request)
      }else{
        fail(request)
      }
    }
  };
  request.send();
}

加载

在设置正确的 Content-Type 的前提下,使用 AJAX 可以轻量级地请求 HTML / CSS / JavaScript / XML / JSON 等内容,只要知道怎么解析这些内容,就可以使用这些内容。解析方法如下:

  • 得到 CSS 之后生成 style 标签
  • 得到 JS 之后生成 script 标签
  • 得到 HTML 之后使用 innerHTML 和 DOM API
  • 得到 XML 之后使用 reponseXML 和 DOM API
  • 得到 JSON 之后使用 JSON.parse
  • 不同类型的数据有不同类型的解析方法

用 AJAX 加载 CSS

getCSS.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/style.css"); //readyState = 1
  request.onreadystatechange = () => {
    //下载完成,但不知道是成功(2xx) 还是失败(4xx 5xx)
    if (request.readyState === 4) {
      if (request.status >= 200 && request.status < 300) {
        //创建 style 标签
        const style = document.createElement("style");
        //填写 style 内容
        style.innerHTML = request.response;
        //插入到 head 里面
        document.head.appendChild(style);
      } else {
        alert("加载 CSS 失败");
      }
    }
  };
  request.send(); //readyState = 2
};

用 AJAX 加载 JS

getJS.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/2.js");
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      if (request.status >= 200 && request.status < 300) {
        //创建 script 标签
        const script = document.createElement("script");
        //填写 script 内容
        script.innerHTML = request.response;
        //插入到 body 里面
        document.body.appendChild(script);
      } else {
        alert("加载 JS 失败");
      }
    }
  };
  request.send();
};

用 AJAX 加载 HTML

getHTML.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/3.html");
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      if (request.status >= 200 && request.status < 300) {
        //创建 div 标签
        const div = document.createElement("div");
        //填写 div 内容
        div.innerHTML = request.response;
        //插入到 body 里面
        document.body.appendChild(div);
      } else {
        alert("加载 HTML 失败");
      }
    }
  };
  request.send();
};

用 AJAX 加载 XML

getXML.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/4.xml");
  request.onreadystatechange = () => {
    if (
      request.readyState === 4 &&
      request.status >= 200 &&
      request.status < 300
    ) {
      //获取 XML 的 DOM 对象
      const dom = request.responseXML;
      //获取内容
      const text = dom.getElementsByTagName("warning")[0].textContent;
      //消除内容中的'回车'
      console.log(text.trim());
    }
  };
  request.send();
};

用 AJAX 加载 JSON

getJSON.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/5.json");
  request.onreadystatechange = () => {
    if (
      request.readyState === 4 &&
      request.status >= 200 &&
      request.status < 300
    ) {
      console.log(request.response);
      const object = JSON.parse(request.response); //字符串转换为对象(反序列化)
      console.log(object);
      myName.textContent = object.name;
    }
  };
  request.send();
};

学习链接

MDN | AJAX

例子

项目示例

封装

通过上面对XMLHttpRequest对象的了解,下面来封装一个简单的ajax请求

//封装一个ajax请求
function ajax(options) {
    //创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()
    //初始化参数的内容
    options = options || {}
    options.type = (options.type || 'GET').toUpperCase()
    options.dataType = options.dataType || 'json'
    const params = options.data
    //发送请求
    if (options.type === 'GET') {
        xhr.open('GET', options.url + '?' + params, true)
        xhr.send(null)
    } else if (options.type === 'POST') {
        xhr.open('POST', options.url, true)
        xhr.send(params)
    //接收请求
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            let status = xhr.status
            if (status >= 200 && status < 300) {
                options.success && options.success(xhr.responseText, xhr.responseXML)
            } else {
                options.fail && options.fail(status)
            }
        }
    }
}

使用方式如下

ajax({
    type: 'post',
    dataType: 'json',
    data: {},
    url: 'https://xxxx',
    success: function(text,xml){//请求成功后的回调函数
        console.log(text)
    },
    fail: function(status){////请求失败后的回调函数
        console.log(status)
    }
})

Promise

大佬文章异步解决方案

什么是异步什么是同步

  • 同步:如果能直接拿到结果就是同步
  • 异步:不能直接拿到结果

异步举例

  • 以AJAX为例
    request.send()之后并不能直接得到response,必须等到readystate变为4之后,浏览器才会回头调用request.onreadystatechange函数。
  • 回调callback
    写给自己用的函数,不是回调,写给别人用的函数是回调。比如request.onreadystatechange就是我写给浏览器调用的函数。

异步和回调的关系

  • 关联
    异步任务需要在得到结果时通知js来取,这时我们可以给js留一个函数地址,异步任务完成时浏览器调用该函数地址,同时把结果作为参数传给该函数,这里的函数是我写给浏览器调用的,所以时回调函数。
  • 区别
    异步任务需要用到回调函数来通知结果 但回调函数不一定只用在异步任务里,也可以用到同步任务中 arr.forEach(n=>console.log(n)) 就是同步回调

判断同步异步

  • 如果一个函数的返回值处于
    1.setTimeout
    2.AJAX(即XMLHttpRequest)
    3.addEventListener 这三个值的内部就是异步函数。
    注意:不要把AJAX设置成同步的,这样会使页面卡住

总结

  • 异步任务不能拿到结果
  • 于是传一个回调给异步任务
  • 异步完成时调用回调
  • 调用时把结果作为参数

promise(解决异步任务的两个结果:成功或失败)

解决异步任务的回调问题

  • 规范回调的名字或顺序
  • 拒绝回调地狱,让代码的可读性更高
  • 很方便的捕获任务

以AJAX为例解释promise

网络异常,图片无法展示
|

核心就是 这一句话

网络异常,图片无法展示
|

总结

  • 第一步
    1.return new Promise((resolve,reject)=>{...})
    2.任务成功调用resolve(result)
    3.任务失败调用reject(onerror)
    4.resolve和reject会再去调用成功和失败函数
  • 第二步
    使用.then(success,fail)传入成功和失败函数

封装AJAX的缺点

  • .post无法上传数据(request.send可以上传)
  • 不能设置请求头(request.setRequestHeader(key,value))

解决方法

  • jQuery.ajax
  • axios(目前最新的ajax库)
    代码示例
    网络异常,图片无法展示
    |

    优点:自动调用JSON.parse,请求拦截器;响应拦截器

Promise的使用

第一步

创建一个promise对象、可以使用new来调用Promise的构造器来进行实例化

return new Promise((resolve,reject)=>{
     // 异步处理
    // 处理结束后、调用resolve 或 reject
})
  • 任务成功时调用resolve(成功) 任务失败时调用reject(失败)
  • resolve 和 reject 都只接受一个参数

第二步

第一步构造出来的promise对象,含有一个 .then() 函数属性使用promise.then() 实例方法,设置其值在 resolve(成功) / reject(失败)时调用的回调函数

promise.then(onFulfilled, onRejected)
  • resolve(成功)时
    onFulfilled 会被调用
  • reject(失败)时
    onRejected 会被调用

举例

使用promise来发送网络请求

function getURL(URL) {
    return new Promise(function (resolve, reject) {
        var req = new XMLHttpRequest();
        req.open('GET', URL, true);
        req.onload = function () {
            if (req.status === 200) {
                resolve(req.responseText);
            } else {
                reject(req.statusText));
            }
        };
        req.onerror = function () {
            reject(req.statusText));
        };
        req.send();
    });
}
var URL = "http://xxx";
getURL(URL).then(function onFulfilled(value){
    console.log(value);
},function onRejected(error){
    console.log(error);
});

Promise还有更高级的用法,链式调用等等,以后在进行总结~

相关文章
|
5月前
|
前端开发
用Promise对象实现的 Ajax
用Promise对象实现的 Ajax
31 0
|
5月前
|
存储 前端开发
PROMISE解决AJAX中的串行和并行
PROMISE解决AJAX中的串行和并行
49 0
|
5月前
|
前端开发 Java
Promise--代码实现-- ajax 传统方式和 promise 方式和 promise 代码优化/重排 方式的对比--综合代码示例
Promise--代码实现-- ajax 传统方式和 promise 方式和 promise 代码优化/重排 方式的对比--综合代码示例
47 0
|
5月前
|
前端开发 API
用promise封装ajax
用promise封装ajax
41 0
|
11月前
|
前端开发 JavaScript API
Promise封装Ajax请求
Promise封装Ajax请求
46 0
|
存储 前端开发
Promise 解决AJAX中的串行并行
Promise 是个好东西!
102 0
|
XML JSON 前端开发
Ajax、Promise、Axios前端三剑客
Ajax、Promise、Axios前端三剑客
|
JSON 前端开发 JavaScript
【JavaScript】Promise(一) —— 理解和使用(是什么、怎么使用、与 Ajax 配合使用、涉及的API)
【JavaScript】Promise(一) —— 理解和使用(是什么、怎么使用、与 Ajax 配合使用、涉及的API)
|
前端开发
ES6 从入门到精通 # 18:使用 Promise 封装 ajax
ES6 从入门到精通 # 18:使用 Promise 封装 ajax
129 0
ES6 从入门到精通 # 18:使用 Promise 封装 ajax
|
前端开发
04 Promise的理解(Ajax)
Promise的理解(Ajax)
04 Promise的理解(Ajax)