1.什么是promise?什么时候使用peomise?
Promise是异步操作的一种解决方案;
其他的异步操作的解决方案还有回调;asyic,await等;
Promise的使用主要还是用来解决层层嵌套的回调函数(call back )的问题;
2.Promise的基本用法
1.Promise实际上是一个构造函数,每次使用的时候需要实例化一个Promise的对象再进行使用;
2.在实例化的Promise构造函数中的参事是一个回调函数,回调函数的参事是resolve和reject;
3. 实例化的promise对象可以调用then方法,该方法有两个函数参数,第一个函数参数是resolve执行之后调用的函数,第二个是reject调用之后执行的函数;
这两个函数参数中的形参是相对应的resolve和reject函数传递的实参;
4.
2.1 Promise的三个状态且Promise的状态一旦发生变化,就不会再进行改变;
pending:在调用构造函数Promise中回调函数的参数resolve函数或者reject函数之前;(未完成)
fulfilled(resolved):在调用reslove函数后;(成功)
rejected:在调用reject函数后;(失败)
Promise状态一旦从未完成状态转变为成功状态或者失败状态之后,就不会发生改变了;
2.2 then()
then 方法执行后返回一个新的 Promise 对象,这个新Promise对象就又可以调用then方法;
但是在Promise的实例对象中,可以通过实例对象的resolve和reject来决定他的then方法中调用哪个函数,而then方法中的参数只有一个是resolve或者reject函数传递的实参,那then方法又怎么决定他返回的Promise对象调用下一个then方法的哪一个函数呢?
#then 方法返回的 Promise 对象的状态改变:
1.在 then 的回调函数中,return 后面的东西,会用 Promise 包装一下,且默认情况下调用的是resolve;(默认返回的永远都是成功状态的 Promise 对象)
2.如果你想要在then方法下返回的是失败状态的Promise对象,可以手写return返回一个完整的失败状态的Promise对象;(reject('err') === throw new Erroe('err'))
const p = new Promise((resolve, reject) => {
reject();
});
p.then(
() => {
console.log('success1');
},
() => {
console.log('err');
// 在 then 的回调函数中,return 后面的东西,会用 Promise 包装一下
// 默认情况下掉的是resolve
// return undefined;
// 等价于
// return new Promise(resolve => {
// resolve(undefined);
// });
// 默认返回的永远都是成功状态的 Promise 对象
return new Promise((resolve, reject) => {
reject('reason');
});
}
)
.then(
data => {
console.log('success2', data);
// 手动返回一个失败状态的Promise对象
return new Promise((resolve,reject) => {
reject(undefined);
});
},
err => {
console.log('err2', err);
}
)
.then(
data => {
console.log('success3', data);
},
err => {
console.log('err3', err);
}
);
3. Promise例子
* {
padding: 0;
margin: 0;
}
#box {
width: 300px;
height: 300px;
background-color: red;
transition: all 0.5s;
}
<div id="box"></div>
const move = (el, { x = 0, y = 0 } = {}, end = () => { }) => {
el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
el.addEventListener(
'transitionend',
() => {
end();
},
false
);
};
const boxEl = document.getElementById('box');
const movePromise = (el, point) => {
return new Promise(resolve => {
move(el,point, () => {
resolve();
});
})
}
console.log(movePromise);
boxEl.addEventListener(
'click',
() => {
movePromise(boxEl, { x: 150 } )
.then(() => {
return movePromise(boxEl, { x: 150, y: 150 });
console.log();
})
.then(() => {
return movePromise(boxEl, {x:0, y: 150 })
})
.then(() => {
return movePromise(boxEl, { x: 0, y: 0 })
})
},
false);
4.catch、then、finally
catch本质上是then的特例,相当于then方法第一个函数参数传入null,第二个参数是正常的函数;
finally与catch一样,本质上也是then的特例,D:\桌面\前端\mook\12 promise&class\12.1 promise\Promise 的实例方法\3-3.catch().html
D:\桌面\前端\mook\12 promise&class\12.1 promise\Promise 的实例方法\3-4.finally().html相当于then方法第一个和第二个函数参数都一样,所以不管结果状态是成功还是失败都会进入finally;一般在开发上来说:
Promise对象如果是成功状态,后面的catch会被忽略,不会影响代码继续进行;
Promise对象如果是失败状态,后面必须有catch来处理错误,没有catch代码不会继续执行;
then专门来处理成功状态;
catch专门来处理失败状态;
finally不管是成功还是失败都会执行;
5. Promise.resolve于Promise.reject
Promise.resolve()是成功状态 Promise 的一种简写形式;
1. (一般数据参数)new Promise(resolve => resolve('foo')); 简写为==> Promise.resolve('foo');
2. (Peomise对象) 当 Promise.resolve() 接收的是 Promise 对象时,直接返回这个 Promise 对象,什么都不做;且后面的 then 会根据传递的 Promise 对象的状态变化决定执行哪一个回调;
3. (具有 then 方法的对象) 如果传入Promise.resolve()中的参数是一个有then的方法,那么会先执行 参数中的then方法,如果对象的then方法中没有return一个Promise对象,后续的then也不会执行;
想要执行后面的then方法,可以在对象的then 方法中使用两个形参接受resolve和reject形参,在对象的函数中使用第一个形参函数执行返回Promise对象;
Promise.reject()是失败状态 Promise 的一种简写形式;
new Promise(reject=> reject('foo')); 简写为==> Promise.reject('foo');
不同于Promise.resolve(),Promise.reject()中的参数,不管是什么参数,都会原封不动地向后传递,作为后续方法的参数;
6.Promise.all()
Promise.all() 关注多个 Promise 对象的状态变化,传入多个 Promise 实例,包装成一个新的 Promise 实例返回;
Promise.all() 的状态变化与所有传入的 Promise 实例对象状态有关;参数是数组,数组中每一个元素都是一个Promise对象;
1. 所有状态都变成 resolved,最终的状态才会变成 resolved;所有的都成功后才会执行then里面的方法;
2. 只要有一个变成 rejected,最终的状态就变成 rejected,且会立即执行then里面的reject对应的第二个函数参数或者catch方法;
3. 所有的状态都是成功时候,传入给then的数据是所有成功返回的数据组成的数组;当有一个是失败状态时候,catch或者then的第二个函数的参数中的err是第一个失败返回的数据,第二个失败时候返回的数据不会传入参数中;
7. Promise.race()与Promise.allSettled();
1. Promise.race()中的参数是一个数组,他的状态取决于第一个完成的 Promise 实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败;
2. Promise.allSettled()传入一个由Promise实例组成的数组,他 的状态与传入的Promise 状态无关,永远都是成功的,他传递给后面then中的数据是一个带有前两个返回值的对象组成的数组;
8.注意
1. 在Peromise实例中的回调函数的resolve和reject执行后,在resolve()或者reject()后面的代码也会执行;一般在会在resolve()和reject()语句前面加上return 关键字,这样后面的就不会执行;
new Promise((resolve, reject) => {
resolve(123)
// return resolve(123);
console.log('测试');
});
2.Promise.all/race/allSettled 的参数问题
参数如果不是 Promise 数组,会将不是 Promise 的数组元素转变成 Promise
Promise.all([1, 2, 3]).then(datas => {
console.log(datas);
});
//等价于
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
]).then(datas => {
console.log(datas);
});
不只是数组,任何可遍历的都可以作为参数,例如数组、字符串、Set、Map、NodeList、arguments
Promise.all(new Set([1, 2, 3])).then(datas => {
console.log(datas);
});
3.Promise.all/race/allSettled 的错误处理
在参数数组中如果某个Promise对象元素是失败状态,那么久需要捕捉错;
方法一:在每一个Promise实例对象后面都加上catch来捕捉错误;
方法二:在Promise.all()之后打点调用catch方法捕捉错误;