Promise
Promise
就是为了解决“回调地狱”问题的,它可以将异步操作的处理变得很优雅。
Promise
可以支持多个并发的请求,获取并发请求中的数据这个 Promise
可以解决异步的问题,本身不能说 Promise
是异步的
定义: 包含异步操作结果的对象
状态:
- pending:[待定]初始状态
- fulfilled:[实现]操作成功
- rejected: [被否决]操作失败
注意:
- Promise 会根据状态来确定执行哪个方法
- Promise 实例化时状态默认为 pending 的,如异步状态异常rejected,反之fulfilled
- 状态转化是单向的,不可逆转,已经确定的状态(fulfilled/rejected)无法转回初始状态(pending),而且只能是从 pending 到 fulfilled 或者 rejected
基本用法
//普通定义
let ajax = (callback) => {
console.log('≈')
setTimeout(() => {
callback && callback.call();
}, 1000)
}
ajax(() => {
console.log('timeout')
})
// 先会打出 开始执行,1s 后打出 timeout
//Promise
let ajax = () => {
console.log("开始执行");
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1000);
});
};
ajax().then(() => {
console.log("timeout");
});
// 先会打出 开始执行,1s 后打出 timeout
// then()
let ajax = () => {
console.log("开始执行");
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1000);
});
};
ajax()
.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 2000);
});
})
.then(() => {
console.log("timeout")
})
// 先会打出 开始执行,3s(1+2) 后打出 timeout
// catch()
let ajax = (num) => {
console.log("开始执行");
return new Promise((resolve, reject) => {
if (num > 5) {
resolve();
} else {
throw new Error("出错了");
}
});
};
ajax(6)
.then(function () {
console.log("timeout"); // 先会打出 开始执行,1s 后打出 timeout
})
.catch(function (err) {
console.log("catch", err);
});
ajax(3)
.then(function () {
console.log("timeout");
})
.catch(function (err) {
console.log("catch"); // 先会打出 开始执行,1s 后打出 catch
});
复制代码
Promise.all() 批量操作
- Promise.all(arr)用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise
- 它接收一个数组作为参数
- 数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
- 当所有的子Promise都完成,该Promise完成,返回值是全部值得数组
- 有任何一个失败,该Promise失败,返回值是第一个失败的子Promise结果
//所有图片加载完成后添加到页面
const loadImg = (src) => {
return new Promise(resolve, reject) => {
let img = document.createElement("img");
img.src = src;
img.onload = function () {
resolve(img);
};
img.onerror = function (err) {
reject(err);
};
});
}
const showImgs = (imgs) => {
imgs.forEach((img) => {
document.body.appendChild(img);
})
}
Promise.all([
loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
]).then(showImgs);
复制代码
Promise.race()
- race 与 all相似,只不过只要有一个执行完就会执行
//有一个执行完就回加载到页面
const loadImg = (src) => {
return new Promise(resolve, reject) => {
let img = document.createElement("img");
img.src = src;
img.onload = function () {
resolve(img);
};
img.onerror = function (err) {
reject(err);
};
});
}
const showImgs = (imgs) => {
let p = document.createElement("p");
p.appendChild(img);
document.body.appendChild(p);
}
Promise.race([
loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
]).then(showImgs);
复制代码
Promise的问题
- 一旦执行,无法中途取消,链式调用多个then中间不能随便跳出来
- 错误无法在外部被捕捉到,只能在内部进行预判处理,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
- Promise内部如何执行,监测起来很难,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。