Promise笔记
promise的初衷是实现异步操作,支持链式回调,处理回调地狱;
实例对象属性
Promise的状态 [PromiseState]
pending 初始状态/未决定的
resolved/fulfilled 成功
rejected 失败
Promise 对象的值
保存对象【成功/失败】的结果
resolve 成功
reject 失败
Promise的方法
Promise.resolve;(value)=>{} value:成功的数据或promise对象
说明:返回一个成功/失败的promise对象
实例:
javascript
let p1 = Promise.resolve(521);
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promise.resolve(new Promise((resolve, reject) => {
resolve('ok')
}))
let p4 = Promise.resolve(new Promise((resolve, reject) => {
reject('err');
}))
console.log(p1); //Promise {<fulfilled>: 521}
console.log(p2); //Promise {<fulfilled>: 'success'}
console.log(p3); //Promise {<fulfilled>: 'ok'}
p4.catch(reason => {
console.log(reason);//err
})
Promise.reject;(reason)=>{} reason:失败的原因
说明:返回一个失败的promise对象,返回结果只能是一个失败的
实例:
javascript
let p1 = Promise.reject(521);
// console.log(p1);//失败这样打印会报错
p1.catch(reason => {
console.log(reason);
})
let p2 = Promise.reject(new Promise((resolve, reject) => {
reject('err');
}))
p2.catch(reason => {
console.log(reason);
})
Promise.all(常用);(promises)=>{} promises:包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才成功(返回PromiseState:fulfilled,PromiseResult:成功的结果),只要有一个失败就直接失败(返回PromiseState:rejected,PromiseResult:失败的结果)
实例:
javascript
let p1 = Promise.resolve(521);
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('成功');
// let p4 = Promise.reject('err');
let result = Promise.all([p1, p2, p3]);
// let result = Promise.all([p1, p2, p4]);
console.log(result);
result.then(value => {
console.log(value);
}).catch(reason => {
console.log(reason);
})
Promise.rase(常用);(promises)=>{} promises:包含n个promise的数组
说明:返回一个新的promise对象,返回第一个完成promise的结果状态;如果所有 Promise 都拒绝,返回的 Promise 也将拒绝,拒绝的理由是一个聚合错误,包含所有 Promise 的拒绝理由。
实例:
javascript
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(521)
}, 1000)
});
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('成功');
let p4 = Promise.reject('err');
// let result = Promise.race([p1, p2, p3]);
let result = Promise.race([p4, p2, p3]);
console.log(result);
Promse.any;(promises)=>{} promises:包含n个promise的数组
说明:返回一个新的promise,返回第一个promise状态成功的结果,如果都没有成功则返回AggregateError类型的实例,它是Error的一个子类,用于把单一的错误集合 在一起;
实例:
javascript
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(521)
}, 1000)
});
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('成功');
let p4 = Promise.reject('err');
let p5 = Promise.reject('fail');
let result = Promise.any([p4, p5])
// let result = Promise.any([p4, p2, p1])
console.log(result);
使用与封装
面试问题
1.promise的状态是否可以改变,如果可以是如何改变的?
答:promise的状态是可以由初始状态pending转为resolved/rejected的状态;但是resolved与rejected之间的状态不能相互转化;
转化的方法:(1)resolve(value):由初始状态转化为resolved;
(2)reject(reason):由初始状态转化为rejected;
(3)抛出异常:例如使用throw由初始状态转化为rejected;
2.一个promise置顶多个成功/失败回调函数,都会调用吗(对于promise的结果使用console.log()与alert()等方法进行多个调用,当状态发生变化时都会进行调用吗)
答:当promise发生改变时对应状态都会调用;
3.改变promise状态和指定回调函数谁先谁后?(改变promise的状态指的就是在new Promise中通过结果来改变其状态;指定回调就是通过then()/catcch()对实例的promise进行回调处理)
答:1.都有可能。在正常情况下是先指定回调在改变状态,但是也可能先改变状态,在执行回调(因为二者是异步进行的,无法判断他们的执行时间)
2.如何先改变状态在指定回调?
(1)在执行器中直接调用resolve()/reject();(2)延长更长时间才调用then(),(在then中使用定时器等方法
)
3.什么时候才能获得数据(对于promise实例完成后传出的数据)
(1)如果先置顶回调,那么当状态发生改变时,回调函数就会调用,得到数据;
(2)如果先改变状态,那么当执行回调时,回调函数就会调用,得到数据;
4.promise.then()返回的新的promise的结果状态又什么决定?(let result = p1.then()中result也是一个promise,其状态又什么决定)
**简单表达:**由then()指定的回调函数执行的结果来决定
详细描述:
1.如果promise中的内容是抛出异常,新的promise状态为rejected,使用reason将异常抛出(例如使用console.log()进行结果展示)
2.如果返回的是有个非promise的任意值,新promise状态将变为resolve,使用value展示结果;
3.如果返回的是另一个新的promise,此promise的结果将会是新的promise的结果;
javascript
// 指定回调:通过p1.then()回调实例
// 改变状态,promise状态从初始状态转化为其他状态
let p1 = new Promise((resolve, reject) => {
resolve('success');
})
let result = p1.then(value => {
// 1.抛出错误
// throw '出了问题';
// 2.返回的是一个非promise的任意值
// return 521;
// 3.返回结果是Promise对象
return new Promise((resolve, reject) => {
// resolve('success');
reject('err');
}, reason => {
console.warn(reason);
})
})
console.log(result);
5.promise如何串联多个操作任务?
1.promise的then()返回一个新的promise,可以写成then()的链式调用;
2.通过then的链式调用串联多个同步/异步任务;
javascript
let p = new Promise((resolve, reject) => {
resolve('OK');
})
p.then(value => {
return new Promise((resolve, reject) => {
resolve('success');
})
}).then(value => {
console.log(value);//success
}).then(value => {
console.log(value);//undefined
})
6.promise异常传透?
1.当使用promise的then的链式调用时,可以在最后指定失败的回调;
2.前面任何操作了异常,都会传到最后失败的回调中处理;(在catch()中显示前面的异常原因)
7.中断promise链?
说明:当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数;
办法:在回调函数中返回一个pendding状态的promise对象;
javascript
let p = new Promise((resolve, reject) => {
resolve('success');
})
p.then(value => {
console.log('111');
// 中断链式的方法:返回一个初始状态的promise
return new Promise(()=>{})
}).then(value => {
console.log('222');
}).then(value => {
console.log('333');
}).catch(reason => {
console.warn(reason);
})
promise的常规使用
node读取文档内容
javascript
const fs = require('fs');
// 原方法读取数据
// fs.readFile("./text/demo1.txt", (err, data) => {
// if (err) throw err;
// console.log(data.toString());
// })
// 使用promise读取数据
const p = new Promise((resolve, reject) => {
fs.readFile("./text/demo1.txt", (err, data) => {
if (err) reject(err);
resolve(data.toString());
})
})
p.then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
// 封装读取方法
const mineReadFile = function (url) {
return new Promise((resolve, reject) => {
fs.readFile(url, (err, data) => {
if (err) reject(err)
resolve(data.toString())
})
})
}
mineReadFile('./text/demo1.txt').then(value => {
console.log(value);
}, reason => {
console.log(reason);
})
使用promise调用ajax
javascript
<button id="demo">点击请求</button>
<script>
// 原生使用
let demo = document.querySelector("#demo")
demo.addEventListener('click', () => {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('GET', 'http://127.0.0.1/my/userList?page=1&pageSize=5&roleId=0');
xhr.setRequestHeader('Authorization',
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiIiwibmFtZSI6IueuoeeQhuWRmCIsInBob25lIjoiNjY2NjYiLCJ1c2VyUGljIjoiaHR0cDovLzEyNy4wLjAuMTo4MC9zdGF0aWMvaW1hZ2UxNzAxNjMyMDA2ODg1LmpwZyIsInJvbGVJZCI6MSwidXNlcl9waWMiOiIiLCJpYXQiOjE3MjcyNzA0MjAsImV4cCI6MTcyNzM1NjgyMH0.SAC-qFKdM0-iLnGO-8wUIf0UE_ylqcSNch8EGOg7hAc'
)
// 3.发送
xhr.send();
// 4.处理响应结果
// 通常处理方法
// xhr.onreadystatechange = function () {
// if (xhr.readyState === 4 && xhr.status === 200) {
// console.log(xhr.response);
// }
// }
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
} else {
console.log(xhr.status);
}
}
}
})
// 使用promise
demo.addEventListener('click', () => {
// 1.创建对象
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts');
// 3.发送
xhr.send();
// 4.处理响应结果
// 通常处理方法
// xhr.onreadystatechange = function () {
// if (xhr.readyState === 4 && xhr.status === 200) {
// console.log(xhr.response);
// }
// }
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response)
} else {
reject(xhr.status)
}
}
}
})
p.then(value => {
console.log(value);
}, reason => {
console.log(reason);
})
})
// promise封装方法
const mineSendAjax = url => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
}
})
}
demo.addEventListener('click', () => {
mineSendAjax('https://jsonplaceholder.typicode.com/posts').then(value => {
console.log(value);
}, reason => {
console.log(reason);
})
})
</script>