前言
前几天同事无意间问我对promise的理解,作为一年前端开发的我,虽然项目里一直有在用,但细细回想promise是什么、怎么用的和我对这个的理解,还真不说不出来,所以我周末就好好花了时间对promise进行了浅层的了解,如果有说错的欢迎指点。
一、promise是什么?为什么会有promise?
首先,promise是js的抽象异步处理对象实现异步编程的方案,简单的说就是解决传统js运行单线程的诟病以及异步操作的多层级嵌套带来的麻烦。
Q:资料说promise是个容器,我对这个理解不是很清晰。
我的理解是说,这个容器指promise的异步操作内容,然后我们这个操作放在这个容器里面让他自己执行,不会受外界影响。
然后,promise有三种状态,分别是:pending、fulfilled、rejected; 当 promise执行resolve是状态由pending->fulfilled; 当 promise执行reject是状态由pending->rejected; 状态一旦改变就不会再变。
二、基本用法
1、实例
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
复制代码
Promise对象是一个构造函数,实例后的Promise是一个对象,该构造函数接受一个函数参数,这个函数参数传入两个参数(resolve,reject), 这两个参数是各是一个函数方法; 我们可以根据函数的结果来判断执行resolve或reject;
2、.then()
promise.then(()=>{
/* resolve 的执行内容 */
},()=>{
/*reject执行的内容*/
}
)
复制代码
.then()方法接受两个函数参数,第一个参数是获取resolve的内容来执行异步操作,第二个参数是执行reject,然后执行一个捕获错误的内容,貌似可以获取代码执行错误的位置; (我的理解:有then方法的promise才是完整的。)
2.1、第一个函数接受一个来自promise的构造函数resolve传递的对象; 3.2、第二个函数会不会promise构造函数的错误;
注意:建议是不推荐 .then(()=>{},()=>{/捕获错误/}) 这样去捕获错误,而是推荐用.catch的方法去捕获错误 .then(()=>{/resolve 内容/}).catch(error){/error捕获错误/}。因为直接在后面点catch()就能够捕获第一次发生错误的地方。
运用promise做多层次的回调 终取到这个节点,但是如果用promise就能够同步异步操作去获取到;
console.log('start');
var promise1 = new Promise((resolve,reject)=>{
setTimeout(resolve('葡萄'),1);
});
promise1.then(value=>new Promise((resolve,reject)=>setTimeout(resolve(value+',苹果'),1)))
.then(value=>new Promise((resolve,reject)=>setTimeout(resolve(value+',橘子'),1)))
.then(value=>new Promise((resolve,reject)=>setTimeout(resolve(value+',香蕉'),1)))
.then(value=>new Promise((resolve,reject)=>setTimeout(resolve(value+',西瓜'),1)))
.then(value=>{console.log(value)});
console.log('上面是个异步过程,所以我先出来,后面才是水果');
/*
控制台打印:
start
上面是个异步过程,所以我先出来,后面才是水果
葡萄,苹果,橘子,香蕉,西瓜
*/
复制代码
这里的then都只执行了成功(resolve)方法,来把前面的只拼接起来传给下个then()方法去接受,下个then的value接受到上面的值继续new Promise 来执行下一个异步操作;
3、.all()
Promise.all() 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then() 方法。
// `delay`毫秒后执行resolve
function timerPromisefy(delay) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(delay);
}, delay);
});
}
var startDate = Date.now();
// 所有promise变为resolve后程序退出
Promise.all([
timerPromisefy(1),
timerPromisefy(32),
timerPromisefy(64),
timerPromisefy(128)
]).then(function (values) {
console.log(Date.now() - startDate + 'ms');
// 約128ms
console.log(values); // [1,32,64,128]
});
复制代码
所以,promise.all,会在所有的参数里的Promise方法执行完再返回所有数据,以数组的格式。
4、.race()
Promise.race()的参数跟all一样是接受一个promise对象数组,不同的是race(),的结果是只要有一个promise变个fulfilled或rejected就能够then()中获取值,然后其他的Promise对象则会继续执行。
// `delay`毫秒后执行resolve
function timerPromisefy(delay) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log(delay)
resolve(delay);
}, delay);
});
}
// 任何一个promise变为resolve或reject 的话程序就停止运行
Promise.race([
timerPromisefy(1),
timerPromisefy(32),
timerPromisefy(64),
timerPromisefy(128)
]).then(function (value) {
console.log('then',value); // => 1
});
控制台
/*
1
32
64
128
then,1
*/
复制代码
三、在react中的运用
1、生命周期的运用
前几天有个需求是要在初次渲染完后获取页面的某个节点,但是我用了reactd的生命周期函数始终取到这个节点,但是如果用promise就能够同步异步操作去获取到;
componentWillMount() {
let P = new Promise((resolve, reject)=>{
console.log('new success')
console.log('promiseNew',document.getElementById('text'))
resolve('8888');
})
P.then((value)=>{
console.log('then','obj',document.getElementById('text'));
})
.catch((error)=>{
console.log('it is error',error)
})
}
componentDidMount(){
this.setState({isFind:true})
console.log('DidMount',document.getElementById("text"))
}
render() {
return (
<div>
{this.state.isFind ? (<Divider id="text">this is PromiseClick</Divider>) : null}
</div>
);
}
/*
控制台打印内容:
new success
promiseNew null
DidMount null
then obj <div class="ant-divider ant-divider-horizontal ant-divider-with-text" id="text">…</div>
*/
复制代码
所以,我的认为是在react的生命周期函数里去执行promise的异步操作,相当于页面加载完再去执行的操作;
2、结合ajax请求的运用
未完,待续。