AJAX(二)

93 阅读4分钟

异步,同步

  • 同步异步不是指时间的长短,而是能否直接拿到结果
  • js执行一行代码,这一行没执行完不拿到结果我是不会走的,这就是同步
  • 同样js执行一行代码,这一行没执行完我先等等再来让你先执行,我一会来拿结果,这就是异步
  • 例子: 以AJAX为例

AJAX有流程,从创建实例开始 ==> open() ==> 监听是否成功 ==> send()

  1. 同步:如果AJAX是同步,那么这四个代码下来到send()函数调用完,等AJAX就执行完了,我们就可以得到结果即response
  2. 如以下代码,send()函数调用完,我们必须等到拿到结果,才会执行下一步,所以console.log(request.response);是有效的
getCss.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/public/style.css",false);
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      const style = document.createElement("style");
      style.innerHTML = request.response;
      document.querySelector("head").appendChild(style);
    }
  };
  request.send();
  console.log(request.response);
};
  1. 异步:send()函数调用完,并不能拿到结果
  2. 以下代码console.log是可以直接拿到response的
getCss.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/public/style.css");
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      const style = document.createElement("style");
      style.innerHTML = request.response;
      document.querySelector("head").appendChild(style);
    }
  };
  request.send();
  console.log(request.response);
};

异步种类

异步有两种一种是代码执行时间太长,你得等一会,另一种是代码现在条件不够不能执行,AJAX就是前者,onreadystatechange就是后者

  1. AJAX就是前者,比方有两个按钮,当你监听点击按钮事件,你按第一个请求CSS,第二个请求HTML,你点击第一个时,不用等到得到结果,你就可以点击第二个,如下图第一个是异步,第二个是同步

  1. AJAX请求只会刷新局部(诞生目的)
  2. onreadystatechange和settimeout就是条件不够异步的,我现在条件不够不能调用等会通知你调用吧

回调,轮询

  • 通常异步通常和回调或者轮询结合
  • 异步就是一会通知你调用/拿结果
  • 如果浏览器自己收到通知就去调用了,那么这个函数就叫回调, onreadystatechange和settimeout的值/参数就是回调
  • 写给别人用的函数就是回调
  • 如果你隔一会儿看看,那么就是轮询

异步,回调

  • 通常异步通常和回调或者轮询结合
  • 拿下面代码为例,就是异步回调,onreadystatechange值就是回调
getCss.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/public/style.css");
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      const style = document.createElement("style");
      style.innerHTML = request.response;
      document.querySelector("head").appendChild(style);
    }
  };
  request.send();
  console.log(request.response);
};
  • onreadystatechange是异步,它的值是回调
  • 异步:我按下这个按钮,你先执行着,我去按下一个按钮去了
  • 回调:你执行完,拿到结果,记得回头调用一下那个函数

异步函数

  • setTimeout,XHR,AddEventListen就是异步
  • 看文档

回调函数

回调函数简写

const array = ['1','2','3'].map(parseInt)

这样简写的前提就是参数一致,等价于

const array = ['1','2','3'].map((item,i,arr) =>{
    return parseInt(item,i,arr)
})

显然是不对的

const array = ['1','2','3'].map((item,i,arr) =>{
    return parseInt(item)
})

map函数:在map里面调用parseInt
调用下面函数,因为parseInt定义的时候也是类似下面函数定义的,虽然map里面看不出parseInt参数,但它实际上是有参数的,简写的原理就讲清了

(item,i,arr) =>{
    return parseInt(item,i,arr)
}

回调总结

const array = ['1','2','3'].map(parseInt)

parseInt(a,b) 虽然map里的parseInt看起来没有参数,但它在定义的时候是有参数(a, b)的,它的逻辑和普通写法是一样的,它定义时的参数(a,b)被赋值,然后调用,这不就是普普通通的传值吗,所以可以这样简写

异步两个结果

假设异步,我们让它自己去执行/自己选时间去执行,那么就有是否执行成功两个结果

  1. 回调接受两个参数
  2. 两个回调
fs.readFile('./1.txt', (error, data)=>{
    if(error){ console.log('失败');
    return
}
console. log(data. toString()) //成功
})
ajax('get ',/1. json',data=>{},error=>{})

AJAX封装

以上方法都不够规范,没有统一规定,代码可读性太差

const ajax = (method, url, options) => {
  const request = new XMLHttpRequest();
  request.open(method, url);
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      if (request.status < 400) {
        options.sucess.call(null, request.response);
      } else {
        options.fail.call(null, request, request.status);
      }
    }
  };
  request.send();
};

首先封装一下AJAX(options是一个对象里面有两个方法)

promise改造

封装之后调用:ajax("GET","/xxx",{success:()=>{},{fail:()=>{}})
改造后:ajax("GET","/xxx").then((response)=>{},(request)=>{},)按照jquery的思想返回一个API,里面有一个then方法,接受两个参数,默认第一个是成功,把函数嵌套变成了.then().then()

const ajax = (method, url, options) => {
  return new Promise((resolve, reject) => {
    const request = new XMLHttpRequest();
    request.open(method, url);
    request.onreadystatechange = () => {
      if (request.readyState === 4) {
        if (request.status < 400) {
          resolve.call(null, request.response);
        } else {
          reject.call(null, request, request.status);
        }
      }
    };
    request.send();
  });
};

只是简单封装了一下GET,而且没有设置请求头,重点在于理解返回API的思想,Promise里面有then()

总结

  1. 异步任务不能拿到结果(两个原因)
  2. 于是我们传一个回调给异步任务
  3. 异步任务完成时调用回调
  4. 调用的时候把结果作为参数,我们对结果进行操作
  5. promise是为了异步的诞生的,异步拿不到的结果给promise就好了
  6. promise是异步和回调结合