一、Promise是什么
简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。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>
参考文章:
https://blog.csdn.net/dkr380205984/article/details/81303171
阮一峰:https://blog.csdn.net/bangbanggangan/article/details/81102052
https://www.cnblogs.com/kazetotori/p/6037940.html
https://blog.csdn.net/weixin_42614080/article/details/90762439