resolve & reject
- Promise.resolve() :创建一个已解决的 Promise,返回指定的值或对象。
- Promise.reject() :创建一个已拒绝的 Promise,返回指定的错误或拒绝原因。
//resolve:Promise.resolve(value)是将值转为值为fulfilled状态的promise,但是如果传入的是promise,
//就原样返回
Promise.resolve = function (value) {
if (value instanceof Promise) {
value
}
return new Promise(resolve => resolve(value))
}
Promise.reject = function (reason) {
return new Promise((resolve, reject) => reject(reason))
}
all
在一组 Promise 中,等待所有 Promise 都解决后,返回一个包含所有解决结果的数组,如果有一个 Promise 被拒绝,返回的 Promise 也会被拒绝。
Promise.all = function (arr) {
const result = []
if (!Array.isArray(arr)) return 'arg is not a Array'
return new Promise((resolve, reject) => {
arr.forEach((p, i) => {
Promise.resolve(p).then(val => {
result[i] = val
if (i === arr.length - 1) {
resolve(result)
}
}, err => {
reject(err)
})
})
})
}
// console.log(Promise)
let p1 = Promise.resolve('success')
let p3 = Promise.reject('error')
// Promise.all([p1, p3]).then((result) => {
// console.log(result)
// }).catch((err) => {
// console.log(err)
// })
race
在一组 Promise 中,返回第一个解决或拒绝的 Promise 的结果或错误,其他 Promise 的结果会被忽略。
function race(arr) {
return new Promise((resolve, reject) => {
arr.forEach(p => {
Promise.resolve(p).then(resolve, reject)
})
})
}
race([p1, p3]).then(result => console.log(result))
function race(arr) {
return new Promise((resolve, reject) => {
arr.forEach(p => {
promise.resolve(p).then(resolve, reject)
})
})
}
这里有个小问题,forEach会执行所有的数组项,但race的特性是
- 如果第一个 Promise 在解决后调用了
resolve,则整个race函数的 Promise 会解决,并且剩下的元素不会执行 - 如果第一个 Promise 在解决后调用了
reject,则整个race函数的 Promise 会拒绝,并且剩下的元素不会执行 - 如果第一个 Promise 没有立即解决也没有立即拒绝,而是在稍后的时间内解决或拒绝,那么在第一个 Promise 解决或拒绝之前,剩下的元素仍然可能会执行。
要在自己的 race 函数中实现 Promise.race() 的特性,我们可以在 forEach 循环中,只处理第一个解决或拒绝的 Promise,并忽略其他 Promise。一种方法是通过添加一个变量来追踪是否已经解决了某个 Promise,然后根据情况来处理。
function race(arr) {
let resolved = false; // 用于追踪是否已经解决了 Promise
return new Promise((resolve, reject) => {
arr.forEach(p => {
p.then(
result => {
if (!resolved) {
resolved = true;
resolve(result); // 第一个解决的 Promise,调用 resolve
}
},
error => {
if (!resolved) {
resolved = true;
reject(error); // 第一个拒绝的 Promise,调用 reject
}
}
);
});
});
}
// 示例用法
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise 1 resolved'), 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise 2 resolved'), 500);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => reject('Promise 3 rejected'), 2000);
});
race([promise1, promise2, promise3])
.then(result => {
console.log('Resolved:', result); // 只会输出第一个解决的 Promise 的结果
})
.catch(error => {
console.error('Rejected:', error); // 只会输出第一个拒绝的 Promise 的错误
});
any
在一组 Promise 中,返回第一个解决的 Promise 的结果,如果所有 Promise 都被拒绝,则返回一个合并的拒绝原因。
Promise.any = function (arr) {
return new Promise((resolve, reject) => {
let completed = 0;
arr.forEach(p => {
Promise.resolve(p).then(resolve).catch(e => {
completed += 1
if (completed === arr.length) {
reject(new AggregateError('All promises were rejected'));
}
})
})
})
}
const promise1 = Promise.reject('Promise 1 rejected');
const promise2 = Promise.reject('Promise 2 resolved');
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => reject('Promise 3 rejected'), 1000);
});
Promise.any([promise1, promise2, promise3])
.then(result => console.log('Resolved:', result))
.catch(error => console.log('Rejected:', error));
并发控制
const fn = url => {
// 实际场景这里用axios等请求库 发请求即可 也不用设置延时
return new Promise(resolve => {
setTimeout(() => {
console.log('完成一个任务', url, new Date());
resolve({ url, date: new Date() });
}, 1000);
})
};
function limitQueue(urls, limit) {
// 完成任务数
let i = 0;
// 填充满执行队列
for (let excuteCount = 0; excuteCount < limit; excuteCount++) {
run();
}
// 执行一个任务
function run() {
// 构造待执行任务 当该任务完成后 如果还有待完成的任务 继续执行任务
new Promise((resolve, reject) => {
const url = urls[i];
i++;
resolve(fn(url))
}).then(() => {
if (i < urls.length) run()
})
}
};
allSettled
在一组 Promise 中,等待所有 Promise 都解决或拒绝后,返回一个包含所有 Promise 的状态(解决或拒绝)和结果的数组。
function customPromiseAllSettled(promises) {
return new Promise(resolve => {
const results = [];
let completedCount = 0;
if (promises.length === 0) {
resolve(results);
return;
}
const handleCompletion = (result, index) => {
results[index] = result;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
};
for (let i = 0; i < promises.length; i++) {
const promise = promises[i];
promise
.then(value => {
handleCompletion({ status: "fulfilled", value }, i);
})
.catch(reason => {
handleCompletion({ status: "rejected", reason }, i);
});
}
});
}
// 示例用法
const promise1 = Promise.resolve(1);
const promise2 = Promise.reject("Error 2");
const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 1000));
customPromiseAllSettled([promise1, promise2, promise3]).then(results => {
console.log(results);
});