当后续的Promise需要用到之前的Promise的处理结果时,需要Promise的串联
Promise对象中,无论是then方法还是catch方法,**它们都具有返回值,返回的是一个全新的Promise对象**,它的状态满足下面的规则:
1. 如果当前的Promise**是未决的,得到的新的Promise是挂起状态
2. 如果当前的Pro**mise是已决的,会运行响应的后续处理函数,并将后续处理函数的结果(返回值)作为resolved状态数据,应用到新的Promise中;如果后续处理函数发生错误,则把返回值作为rejected状态数据,应用到新的Promise中。
后续的Promise一定会等到**前面的Promise有了后续处理结果后,才会变成已决状态
3.如果前面的Promise的后续处理,返回的是一个Promise,则返回的新的Promise状态和后续处理返回的Promise状态保持一致。
示例1
const pro = new Promise ((resolve,reject) =>{
})
const pro2 = pro.then(value =>{
return value;
})
pro2.then(value =>{
console.log(1)
})
当其 unsettled阶段为pending状态 说明此时还没结果,所以后面的settled阶段是不会执行的,后面在得到新的promise也会是pending状态
示例2
如果当前的Pro**mise是已决的,会运行响应的后续处理函数,并将后续处理函数的结果(返回值)作为resolved状态数据,应用到新的Promise中;如果后续处理函数发生错误,则把返回值作为rejected状态数据,应用到新的Promise中。**
const pro = new Promise((resolve,reject) =>{
resolve(1)
})
const pro2 = pro.then(value =>{
throw 2
})
pro2.then(value => console.log(value),err => console.log(err))
pro.then进入啦resolved状态,但是内部代码报错那吗pro2就会接受错误信息进入rejected状态
const pro = new Promise((resolve,reject) =>{
throw 2
})
console.log(pro)
const pro2 = pro.then(value =>{
// throw 2
},err => err * 2 )
pro2.then(value => console.log(value),err => console.log(err * 2 ))
如上面代码,pro在unsettled阶发送需错误信息 但是 pro在rejected状态并没抛出错误,而是进行运算,那这样就是是后续代码没有出现错误,pro2进入resolved 状态,这说明新的promise 进入那种状态时看它的上一个promise后续处理函数是否出错,没出错那就接受resolved状态数据,反之就接受rejected状态数据
示例3
如果前面的Promise的后续处理,返回的**是一个Promise,则返回的新的Promise状态和后续处理返回的Promise状态保持一致
注意then方法与catch放发返回的时promise对象 ,此处说的是返回一个promise**
const pro = new Promise((resolve,reject)=>{
resolve(1)
})
const pro2 = new Promise((resolve,reject)=>{
resolve(2)
})
const pro3 = pro.then(value =>{
//返回一个promise
return pro2;
})
pro3.then(value =>{
console.log(value) // 结果为 2
})
示例4
const pro = new Promise((resolve,reject)=>{
resolve(1)
})
pro.then(value =>{
return 1
}).then(value =>{
value = 2
//函数默认返回值为unfinished
}).then(value =>{
console.log(value) //结果为unfinished
}
此代码中pro的第二个处理函数并没有设置返回值,函数将其默认值unfinished返回,而pro的第三个处理函数却接受的unfinished的值
案例1
回调地狱
<script src="./ajax.js"></script>
<!-- 获取李华所在班级的老师的信息 -->
<script>
ajax({
url: "./data/students.json?name=李华",
success: function (data) {
console.log(data)
for (let i = 0; i < data.length; i++) {
if (data[i].name === '李华') {
const cid = data[i].classId;
ajax({
url: "./data/classes.json?id=" + cid,
success(data) {
console.log(data)
for (let j = 0; j < data.length; j++) {
if (data[j].id === cid) {
const tid = data[j].teacherId;
ajax({
url: "./data/teachers.json?id=" + tid,
success(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].id === tid) {
console.log(data[i])
}
}
}
})
}
}
}
})
}
}
}
})
</script>
promise
// 辅助函数,把传进来的对象拼接成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("&");
}
// 封装Ajax
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, obj.url, obj.async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
let data = toData(obj.data);
xhr.send(data);
} else {
let url = obj.url + "?" + toData(obj.data);
xhr.open(obj.type, url, obj.async);
xhr.send();
}
// 接收返回过来的数据
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
resolve(JSON.parse(xhr.responseText))
} else {
reject(xhr.status)
}
}
}
})
}
// 开始查询
const pro = ajax({
url: './data/students.json'
})
pro.then(value => {
for (let i = 0; i < value.length; i++) {
if (value[i].name === '李华') {
return value[i].classId
}
}
}).then(cid => {
return ajax({
url: "./data/classes.json?id=" + cid,
}).then(value => {
for (let i = 0; i < value.length; i++) {
if (value[i].id === cid) {
return value[i].teacherId
}
}
})
}).then(tid => {
return ajax({
url: "./data/teachers.json?id=" + tid,
}).then(value =>{
for (let i = 0; i < value.length; i++) {
if(value[i].id === tid){
console.log(value[i])
}
}
})
})
从上面两个代码中es6之前的回调地狱的代码及其不易看懂,毕竟嵌套太多观察起来很不容易,es6的promise,并不有减少代码而是消除回调地狱,不会让他无限回调下去而是将回调变得可以控制,把它每一块都分开啦,每一个then方法处理一个步骤处理完后交个下一个promise处理 以此形成一个串联关系