本文介绍: 【代码】面试手写第二期 Promsie相关。
文章目录
一. 手写实现PromiseA+规范
class Mypromise {
state = 'pending'; // 状态 'pending' 'fulfilled' 'rejected'
value = undefined; // 成功后的值
reason = undefined; //
// 如果要是 setTimeout改变状态,就先将回调保存起来
resolveCallbacks = []; // .then的时候 状态为pending时,存储回调
rejectCallbacks = [];
constructor(fn) {
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
console.log(this.resolveCallbacks);
// 状态初始为pending,然后变化后在这里执行 fn
this.resolveCallbacks.forEach((fn) => fn(this.value));
}
};
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.rejectCallbacks.forEach((fn) => fn(this.reason));
}
};
try {
fn(resolveHandler, rejectHandler);
} catch (err) {
rejectHandler(err);
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v;
fn2 = typeof fn2 === 'function' ? fn2 : (err) => err;
// 状态还没有发生改变,存储fn1,fn2
if (this.state === 'pending') {
const p1 = new Mypromise((resolve, reject) => {
// 保存函数
// 当状态改变为fulfilled的时候,执行下面的回调
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value);
resolve(newValue); // p1.value
} catch (error) {
reject(error);
}
});
this.rejectCallbacks.push(() => {
try {
const newRerson = fn2(this.reason);
reject(newRerson); // p1.reason
} catch (error) {
reject(error);
}
});
});
return p1;
}
// 状态已经改变,直接执行
if (this.state === 'fulfilled') {
// 执行完then 返回一个新的promise
const p1 = new Mypromise((resolve, reject) => {
try {
// this.value == resolve(value)里面传的值
const newValue = fn1(this.value);
// 返回新的值
console.log(newValue);
resolve(newValue);
} catch (error) {
reject(error);
}
});
return p1;
}
if (this.state === 'rejected') {
const p1 = new Mypromise((resolve, reject) => {
try {
const newReason = fn2(this.reason);
reject(newReason);
} catch (error) {
reject(error);
}
});
return p1;
}
}
// .catch 是 then的语法糖
catch(fn) {
return this.then(null, fn);
}
finally(fn) {
return this.then((value) => {
return Mypromise.resolve(fn()).then(() => value)
}, err => {
return Mypromise.resolve(fn()).then(() => throw err)
})
}
}
// MyPromise的静态方法
Mypromise.resolve = function (value) {
return new Mypromise((resolve, reject) => resolve(value));
};
Mypromise.reject = function (value) {
return new Mypromise((resolve, reject) => reject(reason));
};
二. Promise.all实现
Mypromise.all = function (promiseList = []) {
const p1 = new Mypromise((resolve, reject) => {
const result = [];
const length = promiseList.length;
let resolveCount = 0;
promiseList.forEach((p, index) => {
p.then((data) => {
result[index] = data;
// resolveCount 必须在 then 里面做 ++
// 不能用index
resolveCount++;
if (resolveCount === length) {
resolve(result);
}
}).catch((err) => {
reject(err);
});
});
});
return p1;
};
三. Promise.race实现
Mypromise.race = function (promiseList = []) {
let resolved = false; // 标记
const p1 = new Promise((resolve, reject) => {
promiseList.forEach((p) => {
p.then((data) => {
if (!resolved) {
resolve(data);
resolved = true;
}
}).catch((err) => {
reject(err);
});
});
});
return p1;
};
四. Promise.allsettled实现
Mypromise.allSettled = function (promiseList = []) {
return new Promise((resolve, reject) => {
const res = [],
len = promiseList.length,
count = len;
promiseList.forEach((item, index) => {
item
.then(
(res) => {
res[index] = { status: 'fulfilled', value: res };
},
(error) => {
res[index] = { status: 'rejected', value: error };
}
)
.finally(() => {
if (!--count) {
resolve(res);
}
});
});
});
};
六. Promise.any实现
Mypromise.any = function(promiseList = []) {
return new HYPromise((resolve, reject) => {
const errors = [];
let rejectedCount = 0
promiseList.forEach((promise, index) => {
HYPromise.resolve(promise).then(
value => {
resolve(value)
},
reason => {
errors[index] = reason;
rejectedCount++;
if (rejectedCount === promiseList.length) {
reject(new AggregateError(errors, 'All promises were rejected'))
}
}
)
})
})
}
六. 如何实现 Promise.map,限制 Promise 并发数
pMap([1, 2, 3, 4, 5], (x) => Promise.resolve(x + 1));
pMap([Promise.resolve(1), Promise.resolve(2)], (x) => x + 1);
// 注意输出时间控制
pMap([1, 1, 1, 1, 1, 1, 1, 1], (x) => sleep(1000), { concurrency: 2 });
class Limit {
constructor (n) {
this.limit = n
this.count = 0
this.queue = []
}
enqueue (fn) {
// 关键代码: fn, resolve, reject 统一管理
return new Promise((resolve, reject) => {
this.queue.push({ fn, resolve, reject })
})
}
dequeue () {
if (this.count < this.limit && this.queue.length) {
// 等到 Promise 计数器小于阈值时,则出队执行
const { fn, resolve, reject } = this.queue.shift()
this.run(fn).then(resolve).catch(reject)
}
}
// async/await 简化错误处理
async run (fn) {
this.count++
// 维护一个计数器
const value = await fn()
this.count--
// 执行完,看看队列有东西没
this.dequeue()
console.log(value);
return value
}
build (fn) {
if (this.count < this.limit) {
// 如果没有到达阈值,直接执行
return this.run(fn)
} else {
// 如果超出阈值,则先扔到队列中,等待有空闲时执行
return this.enqueue(fn)
}
}
}
Promise.map = function (list, fn, { concurrency }) {
const limit = new Limit(concurrency)
return Promise.all(list.map(async (item) => {
item = await item
return limit.build(() => fn(item))
}))
}
const array = [1, 2, 3, 4, 5];
const concurrencyLimit = 2;
const mapper = async (item) => {
// 模拟异步操作
await new Promise((resolve) => setTimeout(resolve, 1000));
return item * 2;
};
Promise.map([Promise.resolve(1), Promise.resolve(2)], mapper, { concurrency: 2 })
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error(error);
});
七. 实现函数 promisify,把回调函数改成 promise 形式
function promisify(fn) {
return function (...args) {
let hasCb = args.some((v) => typeof v === "function");
if (hasCb) {
fn(...args);
} else {
return new Promise((resolve, reject) => {
fn(...args, cb);
function cb(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
}
});
}
};
}
var func1 = function (a, b, c, callback) {
let rst = a + b + c;
callback(null, rst);
};
var func2 = promisify(func1);
func2(1, 2, 3).then((rst) => {
console.log("rst", rst);
}); //输出6
八. 并发请求控制
class ConcurrencyLimiter {
constructor(maxConcurrency) {
this.maxConcurrency = maxConcurrency;
this.activeRequests = 0;
this.queue = [];
}
async enqueue(request) {
await this.waitUntilAllowed();
try {
this.activeRequests++;
const response = await fetch(request.url);
console.log(`Request ${request.id} completed with response:`, response);
} catch (error) {
console.error(`Request ${request.id} failed with error:`, error);
} finally {
this.activeRequests--;
this.processQueue();
}
}
waitUntilAllowed() {
return new Promise((resolve) => {
if (this.activeRequests < this.maxConcurrency) {
resolve();
} else {
this.queue.push(resolve);
}
});
}
processQueue() {
if (this.queue.length > 0 && this.activeRequests < this.maxConcurrency) {
const nextRequest = this.queue.shift();
nextRequest();
}
}
}
// 创建并发器实例,最大请求数量为 5
const limiter = new ConcurrencyLimiter(5);
// 请求列表示例
const requests = [
{ id: 1, url: 'https://api.example.com/data/1' },
{ id: 2, url: 'https://api.example.com/data/2' },
{ id: 3, url: 'https://api.example.com/data/3' },
// 更多请求...
];
// 启动所有请求
requests.forEach((request) => {
limiter.enqueue(request);
});
function fetch(url) {
return new Promise((resolve, reject) => {
resolve(url)
})
}
原文地址:https://blog.csdn.net/qq_63299825/article/details/135948452
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_63811.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。