一、Promise是什么

简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

resolve和reject,这两个参数都是函数。



new Promise(function(resolve,reject){
  异步操作 ajax 定时器等{
    if(结果满意)
      resolve(value)
    else
      reject(error)
  }
})



二、then方法

     Promise 实例生成以后,可以用then 方法分别指定resolve和reject的回调函数。then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供 。这两个函数都接受Promise 对象传出的值作为参数。



function timeout(ms) {
  return new Promise((resolve, reject) => {
    if(ms>=100)
     setTimeout(resolve, ms, 'done'); //setTimeout的第三个参数用于给第一个参数(函数)传参
    else
     setTimeout(reject, ms, 'error'); //setTimeout的第三个参数用于给第一个参数(函数)传参
  });
}
timeout(100).then((value) => {
  console.log(value);  //done
},(error)=>{
  console.log(error)
});
timeout(100).then((value) => {
  console.log(value);
},(error)=>{
  console.log(error)  //error
});



三、promise中 的catch()方法 

  • catch方法用于指定发生错误时的回调
timeout(100).then((value) => {
  console.log(value);  
}.catch((error)=>{
  console.log(error)
});



  • catch可以检测resolve中抛出的异常
timeout(100).then((value) => {
  console.log(value);
  console.log(somethingUndefined)
}).catch((error)=>{
  console.log(error)  //somethingUndefined is not defined
});//如果resolve中发生异常,JS不会报错,而会把错误抛给catch的第一个参数



四、Promise手动封装ajax函数



<script>
       // ajax函数默认的参数
       let ajaxDefaultOptions = {
           url: '#', // 请求地址,默认为空
           method: 'GET', // 请求方式,默认为GET请求
           async: true, // 请求同步还是异步,默认异步
           timeout: 0, // 请求的超时时间
           dataType: 'text', // 请求的数据格式,默认为text
           data: null, // 请求的参数,默认为空
           headers: {}, // 请求头,默认为空
           onprogress: function () {}, // 从服务器下载数据的回调
           onuploadprogress: function () {}, // 处理上传文件到服务器的回调
           xhr: null // 允许函数外部创建xhr传入,但是必须不能是使用过的
       };

       function _ajax(paramOptions) {
          //将传入的参数和默认值合并
           let options = {};
           for (const key in ajaxDefaultOptions) {
               options[key] = ajaxDefaultOptions[key];
           }
           // 如果传入的是否异步与默认值相同,就使用默认值,否则使用传入的参数
           options.async = paramOptions.async === ajaxDefaultOptions.async ? ajaxDefaultOptions.async : paramOptions.async;
           // 判断传入的method是否为GET或者POST,否则传入GET 或者可将判断写在promise内部,reject出去
           options.method = paramOptions.method ? ("GET" || "POST") : "GET";
           // 如果外部传入xhr,否则创建一个
           let xhr = options.xhr || new XMLHttpRequest();
           // return promise对象
           return new Promise(function (resolve, reject) {
               xhr.open(options.method, options.url, options.async);
               xhr.timeout = options.timeout;
               // 设置请求头
               for (const key in options.headers) {
                   xhr.setRequestHeader(key, options.headers[key]);
               }
               // 注册xhr对象事件
               xhr.responseType = options.dataType;

               //从服务器上下载数据每50ms触发一次
               xhr.onprogress = options.onprogress;
               xhr.onuploadprogress = options.onuploadprogress;
               // 开始注册事件
               // onloadend:请求结束,无论成功或者失败
               xhr.onloadend = function () {
                   if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
                       resolve(xhr);
                   } else {
                       reject({
                           errorType: "status_error",
                           xhr: xhr
                       });
                   }
               };
               // 请求超时
               xhr.ontimeout = function () {
                   reject({
                       errorType: "timeout_error",
                       xhr: xhr
                   });
               }
// ,服务器异常,请求错误
               xhr.onerror = function () {
                   reject({
                       errorType: "onerror",
                       xhr: xhr
                   });
               }
// abort错误(未明白,只知道是三种异常中的一种)
               xhr.onabort = function () {
                   reject({
                       errorType: "onabort",
                       xhr: xhr
                   });
               }
// 捕获异常
               try {
                   xhr.send(options.data);
               } catch (error) {
                   reject({
                       errorType: "send_error",
                       error: error
                   });
               }
           });
       }
       
       // 调用示例
       _ajax({
           url: 'http://localhost:3000/suc',
           async: true,
           onprogress: function (evt) {
               console.log(evt.position / evt.total);
           },
           dataType: 'text/json'
       }).then(
           function (xhr) {
               console.log(xhr.response);
           },
           function (e) {
               console.log(JSON.stringify(e))
           });
   </script>