Promise
Promise的基本使用
const pro = new Promise((resolve, reject)=>{
// 未决阶段的处理
// 通过调用resolve函数将Promise推向已决阶段的resolved状态
// 通过调用reject函数将Promise推向已决阶段的rejected状态
// resolve和reject均可以传递最多一个参数,表示推向状态的数据
})
pro.then(data=>{
//这是thenable函数,如果当前的Promise已经是resolved状态,该函数会立即执行
//如果当前是未决阶段,则会加入到作业队列,等待到达resolved状态后执行
//data为状态数据
}, err=>{
//这是catchable函数,如果当前的Promise已经是rejected状态,该函数会立即执行
//如果当前是未决阶段,则会加入到作业队列,等待到达rejected状态后执行
//err为状态数据
})
细节
- 未决阶段的处理函数是同步的,会立即执行
- thenable和catchable函数是异步的,就算是立即执行,也会加入到事件队列中等待执行,并且,加入的队列是微队列
- pro.then可以只添加thenable函数,pro.catch可以单独添加catchable函数
- 在未决阶段的处理函数中,如果发生未捕获的错误,会将状态推向rejected,并会被catchable捕获
- 一旦状态推向了已决阶段,无法再对状态做任何更改
- Promise并没有消除回调,只是让回调变得可控
Promise的串联
当后续的Promise需要用到之前的Promise的处理结果时,需要Promise的串联
Promise对象中,无论是then方法还是catch方法,它们都具有返回值,返回的是一个全新的Promise对象,它的状态满足下面的规则:
- 如果当前的Promise是未决的,得到的新的Promise是挂起状态
- 如果当前的Promise是已决的,会运行响应的后续处理函数,并将后续处理函数的结果(返回值)作为resolved状态数据,应用到新的
Promise中;如果后续处理函数发生错误,则把返回值作为rejected状态数据,应用到新的Promise中。
后续的Promise一定会等到前面的Promise有了后续处理结果后,才会变成已决状态
如果前面的Promise的后续处理,返回的是一个Promise,则返回的新的Promise状态和后续处理返回的Promise状态保持一致。
练习
封装ajax
// 辅助函数,把传进来的对象拼接成url的字符串
function toData(obj) {
if (obj === null) {
return obj;
}
let arr = [];
for (let i in obj) {
let str = i + "=" + obj[i];
arr.push(str);
}
return arr.join("&");
}
function ajax(obj) {
return new Promise((resolve, reject) => {
//指定提交方式的默认值
obj.type = obj.type || "get";
//设置是否为异步,默认为true(异步)
obj.async = obj.async || true;
//设置数据的默认值
obj.data = obj.data || null;
//根据不同的浏览器创建XHR对象
let xhr = null;
if (window.XMLHttpRequest) {
//非IE浏览器
xhr = new XMLHttpRequest();
} else {
//IE浏览器
xhr = new ActiveXObject("Microsoft.XMLHTTP")
}
//区分get和post,发送HTTP请求
if (obj.type === "post") {
xhr.open(obj.type, "open.duyiedu.com" + obj.url, obj.async);
xhr.setRequestHeader("Content-type", "application/x-www-from-urlencoded");
let data = toData(obj.data);
xhr.send(data);
} else {
let url = "https://open.duyiedu.com" + obj.url + '?' + toData(obj.data);
console.log(url);
xhr.open(obj.type, url, obj.async);
xhr.send();
}
//接受返回过来的数据
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr === 304) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(xhr.status);
}
}
}
})
}
ajax({ url: "/api/student/findAll", data: { appkey: 'gansong_1591183714133' } }).then(resp => {
console.log(resp);
}, err => {
console.log(err);
})
Promise例子
function pro(god) {
return new Promise((resolve, reject) => {
console.log(`ganMr向${god}+表白了`);
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(`${god}同意了`);
} else {
reject(`${god}很开心的同意了`);
}
}, 3000);
})
}
pro("xuMiss").then(data => {
console.log(data);
}, err => {
console.log(err);
})
Promise的里的执行顺序
const pro = new Promise((resolve, reject) => {
console.log('a');
resolve(1);
//推向宏队列
setTimeout(() => {
console.log('c');
}, 30);
//推向宏队列
setTimeout(() => {
console.log('b');
}, 0);
})
//推向微队列
pro.then(data => {
console.log(data);
})
console.log("d");
/**
a
d
1
b
c
*/