一、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>