我在下面编写了一些使用Deferred
Promise的代码,而我找到它的最简单方法是使用对象而不是通常的Promise执行程序函数,因为我需要从执行程序外部html" target="_blank">html" target="_blank">解析Promise。我想知道是否存在基于Promise执行程序功能的可接受的设计模式,而不使用类似延迟的解决方案?无需从承诺执行者外部解决承诺就可以做到吗?
这是详细信息。
我有一个项目,该项目使用一组工作线程以及希望不时使用工作线程的代码的各个部分。为了解决这个问题,我创建了一个简单的WorkerList
类,其中列出了可用的工作线程列表。当某人想要使用一个get()
线程时,他们会调用它,并返回一个解析为工作线程的promise。如果辅助线程立即可用,则诺言立即解决。如果所有工作线程都在使用中(因此可用工作线程列表为空),则承诺将无法解析,直到以后通过该add(worker)
方法将一个承诺线程放回到可用列表中。
此WorkerList类只有两个方法,add(worker)
和get()
。您get()
是一个工作人员,当您完成工作后,便将add(worker)
其退回。当您add(worker)
返回时,该类将检查是否有任何任务在等待可用的Worker。如果存在,它将与可用的Worker达成其承诺。解决其他人的诺言的地方就是使用“延期”的地方。
这是的代码WorkerList
:
class WorkerList {
constructor() {
this.workers = [];
this.deferredQueue = [];
}
add(worker) {
this.workers.push(worker);
// if someone is waiting for a worker,
// pull the oldest worker out of the list and
// give it to the oldest deferred that is waiting
while (this.deferredQueue.length && this.workers.length) {
let d = this.deferredQueue.shift();
d.resolve(this.workers.shift());
}
}
// if there's a worker, get one immediately
// if not, return a promise that resolves with a worker
// when next one is available
get() {
if (this.workers.length) {
return Promise.resolve(this.workers.shift());
} else {
let d = new Deferred();
this.deferredQueue.push(d);
return d.promise;
}
}
}
并且,这是Deferred实现:
function Deferred() {
if (!(this instanceof Deferred)) {
return new Deferred();
}
const p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
if (p.finally) {
this.finally = p.finally.bind(p);
}
}
也许下面的内容只是穷人的递延方法,并没有真正解决问题的症结,但是除了递延队列之外,您还可以保留解析器功能队列。
这样可以在您的方法上节省少量代码,并避免显式使用Deferreds。
我不知道是否存在已建立的模式,但是它本身似乎是用于维护异步对象池的可重用模式,因此WorkerList
可以调用它而不是调用它,而是将其命名AsyncPool
为可重用的部分在您的WorkerList
:
class AsyncPool {
constructor() {
this.entries = [];
this.resolverQueue = [];
}
add(entry) {
console.log(`adding ${entry}`);
this.entries.push(entry);
// if someone is waiting for an entry,
// pull the oldest one out of the list and
// give it to the oldest resolver that is waiting
while (this.resolverQueue.length && this.entries .length) {
let r = this.resolverQueue.shift();
r(this.entries.shift());
}
}
// if there's an entry, get one immediately
// if not, return a promise that resolves with an entry
// when next one is available
get() {
return new Promise((r) =>
this.entries.length
? r(this.entries.shift())
: this.resolverQueue.push(r)
);
}
}
let pool = new AsyncPool();
pool.add('Doc');
pool.add('Grumpy');
pool.get().then(console.log);
pool.get().then(console.log);
pool.get().then(console.log);
pool.get().then(console.log);
// add more entries later
setTimeout(() => pool.add('Sneezy'), 1000);
setTimeout(() => pool.add('Sleepy'), 2000);
我不能使用运算符&&或者,如果没有运算符,我如何格式化相同的代码?
问题内容: 是否可以像用C ++一样用Java 编写 虚拟 方法? 或者,是否存在可以实现类似行为的适当Java方法?我可以举一些例子吗? 问题答案: 来自维基百科 在 Java中 ,默认情况下,所有非静态方法都是“ 虚拟函数”。 只有标记为 final的 方法(不能被覆盖)以及 私有方法 (未被继承)都是 非虚拟的 。
是否可以在Visual Studio代码中自定义代码折叠的工作方式? 我使用一种通用模式来定义各种不同文档类型之间的代码区域。 > 所以,对于XML,我用和包装文本部分 对于typescript/JavaScript,我使用和。 在完整的Visual Studio(不是VS代码)中,我有一个自定义扩展,它可以窥探文档类型之间的模式,并基于该模式创建折叠,从而允许我创建整洁的自定义文档大纲。我希望在
问题内容: 我有一个简短的hello world程序: 我使用gcc将其编译为以下汇编代码: 我的问题是:如果我要用汇编语言编写该程序(而不是用C编写然后编译为汇编语言),此代码的所有部分是否必不可少?我了解组装说明,但是有些部分我不理解。例如,我不知道什么是.cfi *,而且我想知道是否需要包括此文件才能在程序集中编写该程序。 问题答案: 可以在这个平台上正常工作的绝对最低要求是 但这违反了许多
在进一步介绍之前,让我们花点时间来讨论编写"通用"代码时的约束条件 - 即运行在服务器和客户端的代码。由于用例和平台 API 的差异,当运行在不同环境中时,我们的代码将不会完全相同。所以这里我们将会阐述你需要理解的关键事项。 服务器上的数据响应 在纯客户端应用程序 (client-only app) 中,每个用户会在他们各自的浏览器中使用新的应用程序实例。对于服务器端渲染,我们也希望如此:每个请求
问题内容: 这与java中的最终接口有关。在讨论中,有一个关于接口的最终概念是模棱两可的。最终接口是否意味着它不能具有子接口?这是否意味着它无法实现? 这个问题是第一个问题:您是否可以编写一个最终接口,以便编译器阻止您实现它? 问题答案: 正如我将展示的,可以使用代理来实现上面的接口。更有意义的问题是,为什么要尝试创建无法实现的界面?即使从哲学角度来说,它似乎也很肤浅。 这不会在编译或运行时产生错