Promise相关实现
请求三秒,超时就中断请求
function delay(t) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(`超出3秒了,您已经请求超时`)
}, t)
})
}
function p2() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('xxx')
}, 4000)
})
}
function timeOutWrapper() {
Promise.race([delay(3000), p2()]).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
}
timeOutWrapper()
JS异步数据流,实现并发异步请求,结果顺序输
const asyncRequest = (url) => new Promise((resolve) => {
setTimeout(() => {
console.log('请求成功了', url)
resolve(`成功响应: ${url}`);
}, Math.random() * 1000)
})
const urls = ['url1', 'url2', 'url3', 'url4', 'url5']
const promises = urls.map(url => asyncRequest(url))
Promise.all(promises).then(results => {
console.log("所有请求完成,按照顺序输出结果:", results)
}).catch(error => {
console.log("请求出错:", error)
})
promise中断请求
class AbortablePromise {
construct(promise) {
this.promise = promise;
this.abort = false
}
abort() {
this.abort = true
}
then(resolve, reject) {
if (this.abort) {
reject(new Error("Promise aborted"))
} else {
return this.promise.then(resolve, reject)
}
}
catch(reject) {
if (this.abort) {
reject(new Promise("Promise aborted"))
} else {
return this.promise.catch(reject)
}
}
finally(onFiinally) {
return this.promise.finally(onFiinally)
}
}
const delay = (ms) => new Promise((resolve => {
setTimeout(resolve, ms)
}))
const abortAbleDelay = new AbortablePromise(delay(3000).then(() => {
console.log("Promise resolved")
}))
abortAbleDelay.abort()
abortAbleDelay.then(() => {
console.log('promise fullfilled')
}, (error) => {
console.log('promise rejected', error.message)
})
setTimeout 补偿系统时间
function mySetTimeout(fn, delay, ...args) {
let currentTime = Date.now()
let timer = null
const task = () => {
currentTime += delay
timer = setTimeout(() => {
fn.apply(this, args)
}, currentTime - Date.now())
}
task()
return clearTimeout(timer)
}
function countDown(duration, callback) {
const startTime = performance.now()
function tick() {
const currentTime = performance.now()
const elapsed = currentTime - startTime
const remaining = duration - elapsed
if (remaining <= 0) {
callback()
} else {
setTimeout(tick, Math.max(0, remaining))
}
}
tick()
}
const duration = 6000
countDown(duration, () => {
console.log('倒计时结束')
})
promise 串行
async function executeSerial(promises) {
for (let p of promises) {
let res = await p
console.log(res)
}
}
let p1 = new Promise(resolve => setTimeout(() => resolve('Promise 1 resolved'), 1000))
let p2 = new Promise(resolve => setTimeout(() => resolve('Promise 2 resolved'), 2000))
let p3 = new Promise(resolve => setTimeout(() => resolve('Promise 3 resolved'), 1000))
const promises = [p1, p2, p3];
executeSerial(promises).then(res => {
console.log('All promises resolved sequentially')
})
function executeSerial2(promises) {
return promises.reduce((p, c) => {
return p.then(c)
}, Promise.resolve())
}
let resArr = executeSerial2(([p1, p2, p3]))
resArr.then(res => {
console.log(res)
})
function promiseSerial(promises) {
let res = Promise.resolve()
promises.forEach(p => {
res = res.then(() => p)
})
}
const promises = new Array(4).fill().map((item, index) => {
return new Promise(resolve => {
setTimeout(() => {
console.log(index);
resolve(index);
}, index * 1000)
})
})
promiseSerial(promises)
const p1 = new Promise((resolve, reject) => {
resolve(123)
})
const p2 = p1.then(res => res * 2)
p2.then(res => {
console.log(res)
})
let pr = new Promise((resolve, reject) => {
throw 1
})
const p3 = pr.then(res => {
return res * 2
}, err => {
return err * 3
})
p3.then(res => {
console.log(res)
})
处理高并发, 100 条数据,带宽为 10, 跑满带宽
function task(){
return new Promise(resolve =>{
setTimeout(()=>{
resolve(+new Date())
} ,1000)
})
}
class asyncProcessQueue {
constructor(max) {
this.poolList = new Set()
this.max = max || 10
this.tasks = []
this.results =[]
}
addTask(task) {
this.tasks.push(task)
}
async runTask() {
for (const task of this.tasks) {
if(this.poolList.size === this.max) {
await Promise.race(this.poolList).catch(err => console.log(err,888))
}
const p = task()
const removeTask = ()=> this.poolList.delete(p)
p.then(removeTask,removeTask)
this.poolList.add(p)
this.results.push(p)
}
return Promise.allSettled(this.results)
}
}
let apq = new asyncProcessQueue(10)
for (let i = 0; i <12; i++) {
apq.addTask(task)
}
apq.runTask().then(res=>{
console.log(res)
})
设计一个简单的任务队列, 要求分别在 1,3,4 秒后打印出 "1", "2", "3"
class TaskQueue{
constructor() {
this.tasks = []
this.currentTask = 0
}
addTask(task,delay) {
this.tasks.push({task,delay})
}
start() {
this.runTask()
}
async runTask() {
if(this.currentTask <this.tasks.length) {
const {task,delay} = this.tasks[this.currentTask]
await this.delay(delay)
task()
this.currentTask++
this.runTask()
}
}
delay(seconds) {
return new Promise(resolve => setTimeout(resolve,seconds*1000))
}
}
const taskQueue = new TaskQueue();
taskQueue.addTask(() => console.log("1"), 1);
taskQueue.addTask(() => console.log("2"), 3);
taskQueue.addTask(() => console.log("3"), 4);
taskQueue.start();
请求五秒未完成就停止
function delay(time) {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(`超出时${time}秒`)
reject('超出时'+time+'秒')
}, time)
})
}
const p2 = new Promise((resolve)=>{
setTimeout(()=>{
console.log('这是正常的请求')
resolve('这是正常的请求')
},6000)
})
function timeOutWrapper(arr) {
Promise.race(arr).then(res=>{
console.log(log(res))
}).catch(err=>{
console.log(err)
})
}
timeOutWrapper([p2, delay(3000)])
实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个
class Scheduler {
constructor() {
this.queue = [];
this.maxNum = 2;
this.runningNum = 0;
}
addTask(time, order) {
const promiseGenerator = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(order)
resolve(order)
}, time)
})
}
this.queue.push(promiseGenerator)
}
start() {
for (let i = 0; i < this.maxNum; i++) {
this.run()
}
}
run() {
if (this.runningNum <= this.maxNum && this.queue && this.queue.length > 0) {
this.queue.shift()().then(res => {
console.log(res)
this.runningNum--
this.run()
})
this.runningNum++
}
}
}
const scheduler = new Scheduler()
const addTask = (time, order) => {
scheduler.addTask(time, order)
}
for (let i = 1; i < 8; i++) {
addTask(i*1000, i)
}
scheduler.start()
并发控制async-pool
async function asyncPool(poolLimit, array, iteratorFn) {
const allTasks = [];
const currentTasks = [];
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item, array));
allTasks.push(p);
if (poolLimit <= array.length) {
const runningTask = p.then(() => currentTasks.splice(currentTasks.indexOf(runningTask), 1));
currentTasks.push(runningTask);
if (currentTasks.length >= poolLimit) {
await Promise.race(currentTasks).then(res => console.log(typeof res));
}
}
}
return Promise.all(allTasks);
}
const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i));
let limit = 3
let array = [1000, 2000, 3000, 4000, 5000, 6000, 7000]
asyncPool(limit, array, timeout).then(res => console.log(res))
function asyncPool(poolLimit, array, iteratorFn) {
let i = 0
const allTasks = []
const currentTask = []
const enqueue = function () {
if (i === array.length) {
return Promise.resolve()
}
const item = array[i++]
const p = Promise.resolve().then(res => iteratorFn(item, i))
allTasks.push(p)
let r = Promise.resolve()
if (poolLimit <= array.length) {
const runTask = p.then(() => currentTask.splice(currentTask.indexOf(p), 1))
currentTask.push(runTask)
if (currentTask.length >= poolLimit) {
r = Promise.race(currentTask)
}
}
return r.then(()=>enqueue())
}
return enqueue().then(()=>Promise.all(allTasks))
}
使用 Promise 实现每隔三秒输出时间
function timeTask(time){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log(new Date())
resolve()
},time)
})
}
const taskRunner = async() =>{
await timeTask(3000)
taskRunner()
}
taskRunner()
Promise.retry 超时重新请求,并在重试一定次数依然失败时输出缓存
const delay = (timeout) => new Promise(resolve => {
setTimeout(resolve, timeout)
})
async function retry(fn, maxAttempts, timeout, cache) {
let count = 0
while (count < maxAttempts) {
try {
return await Promise.race([fn, delay(timeout)])
} catch (e) {
count++
console.log(`Attempt ${count} failed!${e}`)
if (maxAttempts === count) {
return cache
}
}
}
}
const num = 3
const timeOut = 3
const cache = 'Cache'
let p = Promise.reject(new Error('Request failed'))
retry(p, num, timeOut, cache).then(data => {
console.log(data, 666)
}).catch(e => {
console.log(e, 555)
})
每隔1秒打印12345
//let + 闭包
for (let i = 1; i <= 5; i++){
setTimeout(()=>console.log(i),i*1000)
}
const delay = (timeout) => new Promise(resolve => {
setTimeout(() => {
resolve(timeout / 1000)
}, 1000)
})
async function generate() {
for (let i = 1; i < 6; i++) {
let res = await delay(i * 1000)
console.log(res)
}
}
generate()