Promise
本篇只看Promise的用法。
基本用法
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
const promise = new Promise((resolve, reject) => {
resolve('111');
})
promise.then(res => {
console.log(res); // 111
})
const promise2 = new Promise((resolve, reject) => {
reject('222');
})
promise2.then(res => {}, res2 => {
console.log(res2); // 222
})
Peomise新建之后就会立刻执行,看个例子:
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
通常情况下,我们都是这样使用Promise的:
const loadImageAsync = url => {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
通常reject函数的参数是Error对象的实例。关于reject和catch有几个地方需要注意:
1.reject后的东西,一定会进入then中的第二个回调;如果then中没有写第二个回调,则进入catch。如:
const pro1 = () => {
return new Promise((resolve, reject) => {
reject('222')
});
};
export const testPro2 = () => {
pro1().then(res => console.log(res), res2 => console.log(res2)).catch(e => console.log('e-----', e));
}
运行结果:222
如果去掉第二个回调:
export const testPro2 = () => {
pro1().then(res => console.log(res)).catch(e => console.log('e-----', e));
}
结果:e----- 222
2.如果是其他异常如网络异常(比如断网),会直接进入catch而不会进入then的第二个回调。
3.reject()方法的参数,会原封不动的作为 reject 的理由,变成后续方法的参数,这一点和resolve不一样。
3.resolve的东西,一定会进入then的第一个回调,肯定不会进入catch。
const pro1 =() => {
return new Promise((resolve, reject) => {
console.log('test');
resolve('111');
});
};
export const testPro2 = () => {
pro1().catch(e => console.log('e-----', e));
}
结果:test
4.resolve函数的参数除了正常的值以外,还可能是一个Promise实例。如果参数是Promise实例,那么Promise.resolve 将不做任何修改、原封不动地返回这个实例。
举个例子:
const p1 = new Promise((_, reject) => {
setTimeout(() => reject('error'), 3000);
});
const p2 = new Promise(resolve => {
setTimeout(() => resolve(p1), 1000);
});
p2.then(
result => console.log(result),
error => console.log(error) // error
);
注意:由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。
我们可以理解成p2.then 实际上是p1.then。
const test2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('FAIL----')
}, 2000)
})
const test3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(test2);
}, 1000)
})
test3.then(result => console.log('result--', result),
result2 => console.log('result2--', result2)
)
5.Promise 新建后就会立即执行,并且调用resolve或reject后不会终结 Promise的参数函数的执行。
let promise = new Promise(function(resolve) {
console.log("Promise");
resolve();
console.log("!!!")
});
promise.then(function() {
console.log("resolved.");
});
console.log("Hi!");
结果:
// Promise
// !!!
// Hi!
// resolved