javascript - 使用 Promise 的 JavaScript 调度器实现
问题描述
我正在解决这个有趣的 javascript 问题(面试问题),但我一直在思考如何使用 Promise 来实现它。
问题:
用 JavaScript 编写一个调度程序,接受最大并发任务数作为参数并调度任务(每个任务可能需要任意时间才能完成)。
请注意,在继续执行其他任务之前,我们一次只需要执行“n”(并发)任务。
这是我的实现:
var exampleTaskA = function () {
setTimeout(function () {
console.log('Task A Done');
}, 1000);
};
function TaskRunner(concurrency) {
this.limit = concurrency;
this.store = [];
this.len = this.store.length;
}
TaskRunner.prototype.push = function (task) {
this.store.push(task);
function getWorker(store, limit) {
if(!store.length) return;
if(store.length <= limit) {
const cur = store.shift();
if(cur) cur();
getWorker(store, limit);
}
}
getWorker(this.store, this.limit);
}
var task = new TaskRunner(2);
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
我如何使用 promises / async await 来实现它?在推动之前,我应该把所有东西都包装在一个承诺上吗?
有人能解惑吗?
解决方案
因此,如果您可以从您的任务中返回一个承诺,您可以绑定到该承诺then()
,以在任务完成以及何时开始另一个任务时提醒您。
这是一个与您的示例类似的示例,但有一些更改:我们不关心队列的长度——您只想知道有多少活动作业存在。因此,您可以在开始作业时递增active
,在作业完成时递减。
有很多方法,我肯定会这样做,但这里是一个想法的大纲:
const exampleTaskA = (name) => new Promise(resolve => setTimeout(function() {
console.log(`Task ${name} Done`);
resolve()
}, Math.floor(Math.random() * 2000)))
function TaskRunner(concurrency) {
this.limit = concurrency;
this.store = [];
this.active = 0;
}
TaskRunner.prototype.next = function() {
if (this.store.length) this.runTask(...this.store.shift())
}
TaskRunner.prototype.runTask = function(task, name) {
this.active++
console.log(`Scheduling task ${name} current active: ${this.active}`)
task(name).then(() => {
this.active--
console.log(`Task ${name} returned, current active: ${this.active}`)
this.next()
})
}
TaskRunner.prototype.push = function(task, name) {
if (this.active < this.limit) this.runTask(task, name)
else {
console.log(`queuing task ${name}`)
this.store.push([task, name])
}
}
var task = new TaskRunner(2);
task.push(exampleTaskA, 1)
task.push(exampleTaskA, 2)
task.push(exampleTaskA, 3)
task.push(exampleTaskA, 4)
task.push(exampleTaskA, 5)
task.push(exampleTaskA, 6)
task.push(exampleTaskA, 7)
推荐阅读
- css - width vs. flex-basis: [width] - 元素被扩展了?
- marketo - 如何通过 API 在 Marketo 中的列表中添加潜在客户(电子邮件、姓名)
- google-cloud-storage - Google Cloud CDN 忽略超过 3600 的 max-age
- android - WebView 不显示结果
- django - Django 模型 - 接口设计以避免在 父类中定义的 CHILD 类调用方法中传递对象
- excel - 当数据存在于另一列中时循环一个列中的公式
- reactjs - React - componentWillReceiveProps 不调用
- c# - 我可以使用 Matlab Coder 为 C# 项目生成 .Net dll 吗?
- java - 将 JAVA 日期更改为 (dd-MMM-yy) 的 ORACLE 日期格式
- jquery - ASP.NET - 在离开页面或切换选项卡之前警告用户未保存的更改