什么是Promise
ES6提供的一个构造函数,利用链式语法解决回调地狱的层层嵌套问题,让多个异步操作 同步执行时更容易读。
Promise三种状态值
- pending: 就绪/待定; new Promise() 时
- rejected:拒绝,代表失败;触发reject函数后
- fulfilled: 满足,代表成功;触发resolve 函数后
**规定:**只允许从 pending 状态 转换成其他状态
Promise固定格式
new Promise((resolve,reject) => {
// resolve({ name: "resolve" })
reject({ name: "reject" })
})
.then( res => {
console.log('then:', res);
})
.catch( err => {
console.log('catch:', err);
})
- Promise: 承诺
- resolve:解决
- reject:拒绝
- then: 然后
- catch:抓取
Promise与xhr的基本用法
var url1 ='https://douyu.xin88.top/api/room/list?page=1&type=ms'
// 调用
get(url1).then(res => {
console.log('res:', res);
})
.catch(err => console.log('err:', err))
// 封装:
function get(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.send()
xhr.onload = function () {
var data = JSON.parse(xhr.response)
resolve({ data })
}
xhr.onerror = function () {
reject(xhr.response)
}
})
}
var url2 ='https://douyu.xin88.top/api/room/list?page=2&type=ms'
get(url2).then(res => {
console.log('res:', res);
})
.catch(err => console.log('err:', err))
var url3 = 'https://douyu.xin88.top/api/room/list?page=3&type=ms'
get(url3).then(res => {
console.log('res:', res);
})
.catch(err => console.log('err:', err))
通过回调函数 变成回调地狱(很少用比较麻烦)
// 封装一个发送get请求的函数
function get(url, cb) {
var xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.send();
xhr.onload = function () {
var data = JSON.parse(xhr.response)
cb(data) // 通过回调函数 回传数据
}
// 如果失败
xhr.onerror = function () {
cb(null, xhr.response)
}
}
// 使用方式
var url1 = 'https://douyu.xin88.top/api/room/list?page=1&;type=ms'
var url2 = 'https://douyu.xin88.top/api/room/list?page=2&;type=ms'
var url3 = 'https://douyu.xin88.top/api/room/list?page=3&;type=ms'
var url4 = 'https://douyu.xin88.top/api/room/list?page=4&;type=ms'
var url5 = 'https://douyu.xin88.top/api/room/list?page=5&;type=ms'
// 需求:依次获取1 2 3 4 5 页的数据
// 多个异步请求同时发送 无法保障完成顺序
get(url1, data => {
console.log(data);
get(url2, data => {
console.log(data);
get(url3, data => {
console.log(data);
get(url4, data => {
console.log(data);
get(url5, data => {
console.log(data);
})
})
})
})
})
解决回调地狱问题 利用promise和then
- then的设定
- new Promise().then().then().then()…
- 把 回调函数 从嵌套模式 转为链式语法模式 更容易阅读
// 封装:
function get(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.send()
xhr.onload = function () {
var data = JSON.parse(xhr.response)
resolve({ data })
}
xhr.onerror = function () {
reject(xhr.response)
}
})
}
var url1 = 'https://serverms.xin88.top/mall?page=1'
var url2 = 'https://serverms.xin88.top/mall?page=2'
var url3 = 'https://serverms.xin88.top/mall?page=3'
var url4 = 'https://serverms.xin88.top/mall?page=4'
var url5 = 'https://serverms.xin88.top/mall?page=5'
get(url1).then(res => {
console.log(res);
// 第一次 promise结束后 返回下一次 promise的操作
return get(url2)
})
// Promise内部的设定 会让这个then连接在一起
.then(res => {
console.log(res);
return get(url3)
})
.then(res => {
console.log(res);
return get(url4)
})
.then(res => {
console.log(res);
return get(url5)
})
.then(res => {
console.log(res);
})
.catch(err => {console.log(err);})
aal方法 — 一个网页有多个接口可使用
// 假设网页上的内容 需要上方四个接口的数据共同组成
// 发送4个请求监听他们一起下载完毕的时机,在进行后续操作
// Promise 的 all 方法:监听多个promise操作完成的时机
// 参数为数组类 存放 多个 Promise
// all: 需要所有promise 都是 fulfilled 状态 即都成功请求到数据
Promise.all([
get(a), get(b), get(c), get(d)
]).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
allSettled方法
// 所有promise的状态均敲定
// 不管成功还是失败 只要所有promise都完毕 就触发then
Promise.allSettled([
get(a), get(b), get(c), get(d)
]).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
race 和 any方法
// 我们如何确保网络请求一定能成功?如果服务器卡了怎么办?
// 可以使用多服务器提供服务,比如提供四个接口地址 数据相同 来自4个不同的服务器
// 请求时同时请求4个服务器,任意一个请求完毕即可!
// race:竞争; 多个promise 谁先完成fulfilled状态 就用哪个的数据
Promise.race([
get(a), get(b), get(c), get(d)
]).then(res => {
console.log(res);
}).catch(err => console.log(err))
// any: 任何一个promise状态敲定即可 不管成功失败
Promise.any([
get(a), get(b), get(c), get(d)
]).then(res => {
console.log(res);
}).catch(err => console.log(err))