面试题答案
一键面试基于Promise链式调用的解决方案
- 链式调用实现依赖操作:通过将Promise操作依次链式调用,确保前一个操作完成后才执行下一个。例如:
function ioOperation1() {
return new Promise((resolve, reject) => {
// 模拟网络请求或文件读取
setTimeout(() => {
resolve('Result of operation 1');
}, 1000);
});
}
function ioOperation2(result1) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`Result of operation 2 with input ${result1}`);
}, 1000);
});
}
ioOperation1()
.then(result1 => ioOperation2(result1))
.then(finalResult => {
console.log(finalResult);
})
.catch(error => {
console.error('Error:', error);
});
- 并发控制:使用
Promise.all
或Promise.race
进行并发操作控制。例如,如果有多个独立的Promise操作可以并发执行,但要等到所有操作完成,可以使用Promise.all
:
function ioOperationA() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Result of A');
}, 1500);
});
}
function ioOperationB() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Result of B');
}, 1000);
});
}
Promise.all([ioOperationA(), ioOperationB()])
.then(results => {
console.log(results);
})
.catch(error => {
console.error('Error:', error);
});
如果只需要第一个完成的Promise结果,可以使用Promise.race
:
Promise.race([ioOperationA(), ioOperationB()])
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
避免阻塞主线程
- 使用微任务队列:Promise的回调是放入微任务队列中的,这意味着它们会在当前宏任务结束后,下一个宏任务开始前执行。这可以避免阻塞主线程,让主线程有机会处理其他任务。例如,DOM渲染等操作可以在Promise回调执行前完成。
- Web Workers(适用于CPU密集型任务):对于一些CPU密集型的计算,如果在Promise操作中存在,可以使用Web Workers将这些任务放到后台线程执行,避免阻塞主线程。例如:
// main.js
const worker = new Worker('worker.js');
worker.onmessage = function(event) {
console.log('Result from worker:', event.data);
};
worker.postMessage('Some data to process');
// worker.js
self.onmessage = function(event) {
// 模拟CPU密集型计算
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += i;
}
self.postMessage(result);
};
处理大量Promise并发时的内存问题
- 限制并发数量:使用队列和
Promise.all
的组合来限制同时执行的Promise数量。例如:
function limitConcurrentPromises(promises, limit) {
return new Promise((resolve, reject) => {
let completedCount = 0;
let results = [];
const executeNext = () => {
if (promises.length === 0 && completedCount === results.length) {
resolve(results);
return;
}
const currentPromises = promises.splice(0, limit);
Promise.all(currentPromises)
.then(values => {
results = results.concat(values);
completedCount += values.length;
executeNext();
})
.catch(error => {
reject(error);
});
};
executeNext();
});
}
// 使用示例
const manyPromises = Array.from({ length: 100 }, (_, i) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`Promise ${i} completed`);
}, 100 * i);
});
});
limitConcurrentPromises(manyPromises, 10)
.then(results => {
console.log(results);
})
.catch(error => {
console.error('Error:', error);
});
- 及时释放资源:在Promise操作完成后,及时释放相关资源,如关闭文件句柄、取消网络请求等,以避免内存泄漏。例如,在Node.js中读取文件后及时关闭文件描述符:
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
const closeFile = util.promisify(fs.close);
const fd = fs.openSync('test.txt', 'r');
readFile(fd, 'utf8')
.then(data => {
console.log(data);
return closeFile(fd);
})
.catch(error => {
console.error('Error:', error);
});