all方法
- Promise的all静态方法:
- 1.all方法接收一个数组,
- 2.如果数组中有多个Promise对象,只有都成功才会执行then方法,并且会按照添加的顺序, 将所有成功的结果重新打包到一个数组中返回给我们
- 3.如果数组中不是Promise对象,那么会直接执行then方法
let arr = [
"http://www.it666.com/files/system/block_picture_1555415767.png",
"http://www.it666.com/files/system/block_picture_1555422597.jpg",
"http://www.it666.com/files/system/block_picture_1555419713.jpg"
];
function loadImage(url) {
return new Promise(function (resolve, reject) {
let oImg = new Image();
let time = Math.random() * 1000;
// console.log(time);
setTimeout(function () {
oImg.src = url;
}, time);
// oImg.src = url;
oImg.onload = function () {
resolve(oImg);
}
oImg.onerror = function () {
reject("图片加载失败了");
}
});
}
for(let i = 0; i < arr.length; i++){
loadImage(arr[i]).then(function (oImg) {
console.log(i);
document.body.appendChild(oImg);
}, function (msg) {
console.log(msg);
});
}
- 示例2:无序加载图片,只有所有图片都加载成功才添加, 有一张图片失败都不添加
- 应用场景: 批量加载, 要么一起成功, 要么一起失败
function loadImage(url) {
return new Promise(function (resolve, reject) {
let oImg = new Image();
let time = Math.random() * 1000;
// console.log(time);
setTimeout(function () {
oImg.src = url;
}, time);
// oImg.src = url;
oImg.onload = function () {
resolve(oImg);
}
oImg.onerror = function () {
reject("图片加载失败了");
}
});
}
/* 有序的写法:
let p1 = new Promise(function (resolve, reject) {
// resolve("111");
reject("aaa");
});
let p2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("222");
}, 5000);
});
let p3 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("333");
}, 3000);
});
Promise.all([p1, p2, p3]).then(function (result) {
console.log("成功", result);
}, function (err) {
console.log("失败", err);
});
*/
// 无序的写法:
Promise.all([loadImage(arr[0]), loadImage(arr[1]),loadImage(arr[2])])
.then(function (result) {
// console.log(result);
result.forEach(function (oImg) {
document.body.appendChild(oImg);
});
})
.catch(function (e) {
console.log(e);
});
all方法实现
- Promise的all静态方法特点
- all方法会返回一个新的Promise对象
- 会按照传入数组的顺序将所有Promise中成功返回的结果保存到一个新的数组返回
- 数组中有一个Promise失败就会失败,只有所有成功才会成功
class MyPromise{
static all(list){
return new MyPromise(function (resolve, reject) {
let arr = [];
let count = 0;
for(let i = 0; i < list.length; i++){
let p = list[i];
p.then(function (value) {
arr.push(value);
count++;
if(list.length === count){
resolve(arr);
}
}).catch(function (e) {
reject(e);
});
}
});
}
}
// 测试:
let p1 = new MyPromise(function (resolve, reject) {
// resolve("111");
reject("aaa");
});
let p2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve("222");
}, 5000);
});
let p3 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve("333");
}, 3000);
});
let pp = MyPromise.all([p1, p2, p3]);
console.log(pp);
pp.then(function (result) {
console.log("成功", result);
}, function (err) {
console.log("失败", err);
});
race方法
- Promise的race静态方法:
- 1.all方法接收一个数组
- 2.如果数组中有多个Promise对象,谁先返回状态就听谁的, 后返回的会被抛弃
- 3.如果数组中不是Promise对象,那么会直接执行then方法
let p1 = new Promise(function (resolve, reject) {
// resolve("111");
reject("aaa");
});
let p2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("222");
// reject("bbb");
}, 5000);
});
let p3 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("333");
// reject("ccc");
}, 3000);
});
Promise.race([p1, p2, p3]).then(function (value) {
console.log("成功", value);
}).catch(function (e) {
console.log("失败", e); // 失败aaa,因为先执行的肯定是P1,所以p2/p3被抛弃
});
let url = "http://www.it666.com/files/system/block_picture_1555415767.png";
function loadImage(url) {
return new Promise(function (resolve, reject) {
let oImg = new Image();
setTimeout(function () {
oImg.src = url;
}, 5000); // 改为3秒内,就会执行这个,输出变成成功
oImg.onload = function () {
resolve(oImg);
}
oImg.onerror = function () {
reject("图片加载失败了");
}
});
}
function timeout() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
reject("超时了");
}, 3000);
});
}
Promise.race([loadImage(url), timeout()]).then(function (value) {
console.log("成功", value);
}).catch(function (e) {
console.log("失败", e); // 失败 超时了
});
race方法实现
- Promise的race静态方法特点
- 1.race方法会返回一个新的Promise对象
- 2.谁先返回就听谁的
class MyPromise{
static race(list){
return new MyPromise(function (resolve, reject) {
for(let p of list){
p.then(function (value) {
resolve(value);
}).catch(function (e) {
reject(e);
});
}
})
}
}
// 测试:
let p1 = new MyPromise(function (resolve, reject) {
// resolve("111");
reject("aaa");
});
let p2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve("222");
// reject("bbb");
}, 5000);
});
let p3 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve("333");
// reject("ccc");
}, 3000);
});
MyPromise.race([p1, p2, p3]).then(function (value) {
console.log("成功", value);
}).catch(function (e) {
console.log("失败", e);
});
promise静态方法最终版
// 定义常量保存对象的状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise{
constructor(handle){
// 0.初始化默认的状态
this.status = PENDING;
// 定义变量保存传入的参数
this.value = undefined;
this.reason = undefined;
// 定义变量保存监听的函数
// this.onResolvedCallback = null;
// this.onRejectedCallback = null;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
// 1.判断是否传入了一个函数, 如果没有传入就抛出一个异常
if(!this._isFunction(handle)){
throw new Error("请传入一个函数");
}
// 2.给传入的函数传递形参(传递两个函数)
handle(this._resolve.bind(this), this._reject.bind(this));
}
then(onResolved, onRejected){
return new MyPromise((nextResolve, nextReject) => {
// 1.判断有没有传入成功的回调
if(this._isFunction(onResolved)){
// 2.判断当前的状态是否是成功状态
if(this.status === FULFILLED){
try {
// 拿到上一个promise成功回调执行的结果
let result = onResolved(this.value);
// console.log("result", result);
// 判断执行的结果是否是一个promise对象
if(result instanceof MyPromise){
result.then(nextResolve, nextReject);
}else{
// 将上一个promise成功回调执行的结果传递给下一个promise成功的回调
nextResolve(result);
}
}catch (e) {
nextReject(e);
}
}
}
// 1.判断有没有传入失败的回调
// if(this._isFunction(onRejected)){
try {
// 2.判断当前的状态是否是失败状态
if(this.status === REJECTED){
let result = onRejected(this.reason);
if(result instanceof MyPromise){
result.then(nextResolve, nextReject);
}else if(result !== undefined){
nextResolve(result);
}else{
nextReject();
}
}
}catch (e) {
nextReject(e);
}
// }
// 2.判断当前的状态是否是默认状态
if(this.status === PENDING){
if(this._isFunction(onResolved)){
// this.onResolvedCallback = onResolved;
this.onResolvedCallbacks.push(() => {
try {
let result = onResolved(this.value);
if(result instanceof MyPromise){
result.then(nextResolve, nextReject);
}else{
nextResolve(result);
}
}catch (e) {
nextReject(e);
}
});
}
// if(this._isFunction(onRejected)){
// this.onRejectedCallback = onRejected;
this.onRejectedCallbacks.push(() => {
try {
let result = onRejected(this.reason);
if(result instanceof MyPromise){
result.then(nextResolve, nextReject);
}else if(result !== undefined){
nextResolve(result);
}else{
nextReject();
}
}catch (e) {
nextReject(e);
}
});
// }
}
});
}
catch(onRejected){
return this.then(undefined, onRejected);
}
_resolve(value){
// 这里是为了防止重复修改
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value;
// this.onResolvedCallback(this.value);
this.onResolvedCallbacks.forEach(fn => fn(this.value));
}
}
_reject(reason){
if(this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// this.onRejectedCallback(this.reason);
this.onRejectedCallbacks.forEach(fn => fn(this.reason));
}
}
_isFunction(fn){
return typeof fn === "function";
}
static all(list){
return new MyPromise(function (resolve, reject) {
let arr = [];
let count = 0;
for(let i = 0; i < list.length; i++){
let p = list[i];
p.then(function (value) {
arr.push(value);
count++;
if(list.length === count){
resolve(arr);
}
}).catch(function (e) {
reject(e);
});
}
});
}
static race(list){
return new MyPromise(function (resolve, reject) {
for(let p of list){
p.then(function (value) {
resolve(value);
}).catch(function (e) {
reject(e);
});
}
})
}
}
用promise改造Ajax的封装
<script>
function obj2str(data) {
data = data || {};
data.t = new Date().getTime();
var res = [];
for(var key in data){
res.push(encodeURIComponent(key)+"="+encodeURIComponent(data[key]));
}
return res.join("&");
}
function ajax(option) {
return new Promise(function (resolve, reject) {
// 0.将对象转换为字符串
var str = obj2str(option.data);
// 1.创建一个异步对象
var xmlhttp, timer;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和请求地址
if(option.type.toLowerCase() === "get"){
xmlhttp.open(option.type, option.url+"?"+str, true);
// 3.发送请求
xmlhttp.send();
}else{
xmlhttp.open(option.type, option.url,true);
// 注意点: 以下代码必须放到open和send之间
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(str);
}
// 4.监听状态的变化
xmlhttp.onreadystatechange = function (ev2) {
if(xmlhttp.readyState === 4){
clearInterval(timer);
// 判断是否请求成功
if(xmlhttp.status >= 200 && xmlhttp.status < 300 ||
xmlhttp.status === 304){
// 5.处理返回的结果
// console.log("接收到服务器返回的数据");
// option.success(xmlhttp);
resolve(xmlhttp);
}else{
// console.log("没有接收到服务器返回的数据");
// option.error(xmlhttp);
reject(xmlhttp);
}
}
}
// 判断外界是否传入了超时时间
if(option.timeout){
timer = setInterval(function () {
console.log("中断请求");
xmlhttp.abort();
clearInterval(timer);
}, option.timeout);
}
});
}
</script>
ajax({
type:"post",
url:"40.php",
// 改成promise监听状态是否成功,就不用以下代码,改为then了
// success: function (xhr) {
// let str = xhr.responseText;
// let json = JSON.parse(str);
// console.log(json);
// },
// error: function (xhr) {
// console.log(xhr.status);
// }
}).then(function (xhr) {
let str = xhr.responseText;
let json = JSON.parse(str);
console.log(json);
}).catch(function (xhr) {
console.log(xhr.status);
});