在Linux环境下,使用JavaScript进行并发控制可以通过多种方式实现,具体取决于你所使用的JavaScript运行环境(如Node.js或浏览器)。以下是几种常见的方法:
async/await 和 Promise.all这是最常用的并发控制方法之一,适用于Node.js和现代浏览器。通过将异步操作封装在Promise中,并使用Promise.all来并行执行多个任务,同时控制并发数量。
const async = require('async');
// 模拟异步任务
function asyncTask(item) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`任务完成: ${item}`);
resolve(item);
}, 1000);
});
}
// 控制并发数的函数
async function runTasks(tasks, concurrency) {
const results = [];
const executing = [];
for (const task of tasks) {
const p = asyncTask(task).then(result => {
results.push(result);
executing.splice(executing.indexOf(p), 1);
});
results.push(p);
executing.push(p);
if (executing.length >= concurrency) {
await Promise.race(executing);
}
}
await Promise.all(executing);
return results;
}
// 使用示例
const tasks = Array.from({ length: 20 }, (_, i) => `任务${i + 1}`);
runTasks(tasks, 5).then(results => {
console.log('所有任务完成:', results);
});
p-limitp-limit 是一个轻量级的库,用于限制并发Promise的数量。
npm install p-limit
const pLimit = require('p-limit');
// 模拟异步任务
function asyncTask(item) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`任务完成: ${item}`);
resolve(item);
}, 1000);
});
}
const limit = pLimit(5); // 限制并发数为5
const tasks = Array.from({ length: 20 }, (_, i) => `任务${i + 1}`);
const promises = tasks.map(task => limit(() => asyncTask(task)));
Promise.all(promises).then(results => {
console.log('所有任务完成:', results);
});
co 库生成器函数可以与co库结合使用,以实现更简洁的并发控制。
co:npm install co
const co = require('co');
// 模拟异步任务
function asyncTask(item) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`任务完成: ${item}`);
resolve(item);
}, 1000);
});
}
// 控制并发数的生成器函数
function* runTasks(tasks, concurrency) {
const results = [];
const queue = tasks.slice();
while (queue.length > 0) {
const workers = Array.from({ length: concurrency }, () => queue.shift());
const done = yield Promise.all(workers.map(task => asyncTask(task)));
results.push(...done);
}
return results;
}
co(runTasks.bind(null, Array.from({ length: 20 }, (_, i) => `任务${i + 1}`), 5)).then(results => {
console.log('所有任务完成:', results);
});
Node.js原生不支持多线程,但可以使用第三方库如worker_threads来创建线程池,实现并发控制。
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
const numTasks = 20;
const concurrency = 5;
const tasks = Array.from({ length: numTasks }, (_, i) => `任务${i + 1}`);
const workers = [];
let completed = 0;
const results = [];
function runWorker() {
if (tasks.length === 0) {
console.log('所有任务完成:', results);
process.exit(0);
return;
}
const task = tasks.shift();
const worker = new Worker(__filename);
worker.postMessage(task);
workers.push(worker);
worker.on('message', (result) => {
results.push(result);
completed++;
workers.splice(workers.indexOf(worker), 1);
runWorker();
});
worker.on('error', (err) => {
console.error(err);
workers.splice(workers.indexOf(worker), 1);
runWorker();
});
worker.on('exit', (code) => {
if (code !== 0)
console.error(`Worker stopped with exit code ${code}`);
workers.splice(workers.indexOf(worker), 1);
runWorker();
});
}
runWorker();
} else {
parentPort.on('message', async (task) => {
// 模拟异步任务
await new Promise(resolve => setTimeout(resolve, 1000));
parentPort.postMessage(`完成: ${task}`);
});
}
在Node.js中,可以利用事件循环和事件驱动的特性,通过自定义事件来管理并发任务。
const EventEmitter = require('events');
class TaskManager extends EventEmitter {
constructor(concurrency) {
super();
this.concurrency = concurrency;
this.running = 0;
this.queue = [];
}
addTask(task) {
this.queue.push(task);
this.next();
}
next() {
while (this.running < this.concurrency && this.queue.length > 0) {
const task = this.queue.shift();
this.running++;
task().then(result => {
this.emit('taskDone', result);
}).catch(err => {
this.emit('taskError', err);
}).finally(() => {
this.running--;
this.next();
});
}
}
}
// 使用示例
const taskManager = new TaskManager(5);
const tasks = Array.from({ length: 20 }, (_, i) => () =>
new Promise((resolve) => {
setTimeout(() => {
console.log(`任务完成: ${i + 1}`);
resolve(`结果${i + 1}`);
}, 1000);
})
);
tasks.forEach(task => taskManager.addTask(task));
taskManager.on('taskDone', result => {
console.log('任务结果:', result);
});
taskManager.on('taskError', err => {
console.error('任务出错:', err);
});
在Linux环境下使用JavaScript进行并发控制,主要依赖于Promise、async/await以及第三方库如p-limit等工具。选择具体的方法应根据项目需求、运行环境以及个人偏好来决定。对于Node.js,还可以利用多线程或事件驱动的方法来实现更复杂的并发控制。