webDevInterviewQuestions/algorithm/04-practical-scenarios.md
2026-01-19 09:34:13 +08:00

236 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 实际场景与逻辑题
## 1. 并发控制(限制并发请求数)
```js
async function limitConcurrency(tasks, limit) {
const results = [];
const executing = [];
for (const [index, task] of tasks.entries()) {
const p = Promise.resolve().then(() => task()).then(res => {
results[index] = res;
executing.splice(executing.indexOf(p), 1);
});
executing.push(p);
if (executing.length >= limit) {
await Promise.race(executing);
}
}
await Promise.all(executing);
return results;
}
// 使用示例
const tasks = urls.map(url => () => fetch(url));
await limitConcurrency(tasks, 3); // 最多3个并发
```
### 异步任务调度器
```js
class Scheduler {
constructor(limit) {
this.limit = limit;
this.queue = [];
this.running = 0;
}
add(promiseCreator) {
return new Promise((resolve, reject) => {
this.queue.push({ promiseCreator, resolve, reject });
this.run();
});
}
run() {
while (this.running < this.limit && this.queue.length) {
const { promiseCreator, resolve, reject } = this.queue.shift();
this.running++;
promiseCreator()
.then(resolve, reject)
.finally(() => { this.running--; this.run(); });
}
}
}
```
---
## 2. 缓存函数Memoization
```js
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// 支持过期时间
function memoizeWithTTL(fn, ttl = 60000) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
const cached = cache.get(key);
if (cached && Date.now() - cached.time < ttl) {
return cached.value;
}
const result = fn.apply(this, args);
cache.set(key, { value: result, time: Date.now() });
return result;
};
}
```
---
## 3. 解析 URL 参数
```js
function parseQuery(url) {
const query = url.split('?')[1] || '';
return query.split('&').reduce((acc, pair) => {
const [key, value] = pair.split('=').map(decodeURIComponent);
if (key) {
acc[key] = acc[key]
? [].concat(acc[key], value)
: value;
}
return acc;
}, {});
}
// 使用正则
function parseQueryRegex(url) {
const result = {};
url.replace(/[?&]([^=&#]+)=([^&#]*)/g, (_, key, value) => {
result[decodeURIComponent(key)] = decodeURIComponent(value);
});
return result;
}
// 示例: "https://example.com?a=1&b=2&a=3"
// => { a: ['1', '3'], b: '2' }
```
---
## 4. DOM 查找最近公共祖先
```js
function findCommonAncestor(node1, node2) {
const ancestors = new Set();
// 收集 node1 的所有祖先
let current = node1;
while (current) {
ancestors.add(current);
current = current.parentNode;
}
// 查找 node2 的祖先中第一个在 ancestors 中的节点
current = node2;
while (current) {
if (ancestors.has(current)) return current;
current = current.parentNode;
}
return null;
}
// 原生方法(现代浏览器)
// node1.compareDocumentPosition(node2)
```
---
## 5. 懒加载/无限滚动
```js
// IntersectionObserver 实现懒加载
function lazyLoad(selector) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll(selector).forEach(img => observer.observe(img));
}
// 无限滚动
function infiniteScroll(container, loadMore) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) loadMore();
});
// 监听底部占位元素
const sentinel = document.createElement('div');
container.appendChild(sentinel);
observer.observe(sentinel);
}
```
---
## 6. LRU 缓存
```js
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) return -1;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) this.cache.delete(key);
this.cache.set(key, value);
if (this.cache.size > this.capacity) {
this.cache.delete(this.cache.keys().next().value);
}
}
}
```
---
## 7. 大数相加
```js
function addBigNumbers(a, b) {
const maxLen = Math.max(a.length, b.length);
a = a.padStart(maxLen, '0');
b = b.padStart(maxLen, '0');
let carry = 0, result = '';
for (let i = maxLen - 1; i >= 0; i--) {
const sum = +a[i] + +b[i] + carry;
result = (sum % 10) + result;
carry = Math.floor(sum / 10);
}
return carry ? carry + result : result;
}
// 示例: addBigNumbers("12345678901234567890", "98765432109876543210")
```