javascript - 对某些回调具有优先级的 Promise 回调队列
问题描述
我的代码需要同时执行大量异步操作,并以特定的顺序方式处理它们的承诺。
我所说的“特定顺序方式”的意思==>假设您正在按顺序启动 promises promise1
, promise2
,promise3
并且 promise3 实际上首先解决,然后 promise2 其次,然后我想要的是 process promise3
,promise2
并按promise1
顺序
让我们考虑一个timeout
异步函数,它在 X 秒后超时,并且fetchMyItem1
, fetchMyItem2
,它返回承诺,当履行时,应该根据是否timeout
已解决执行不同的代码。
对于一个具体的场景,假设有一位顾客在柜台等待一件物品送达,或者顾客留下来,我们可以一次拿一件物品直接在柜台为他服务,或者顾客离开 ( timeout
)我们必须请服务员来,以便在物品到达时,他/她可以将物品带给他。请注意,即使一件商品正在交付,其他商品也应该仍在交付中(承诺待定),甚至可能在为客户提供一件商品或服务器到达时到达(履行)。
这是一些开始的代码
const allItemsToBeDeliveredPromises = [fetchMyItem1(), fetchMyItem2(), ...]
const customerLeavesCounterPromise = timeout()
const waiter = undefined
const allPromisesToBeFulfilled = [...allItemsToBeDeliveredPromises, customerLeavesCounterPromise]
// LOOP
const itemDeliveredOrVisitorLeft = await Promise.all(allPromisesToBeFulfilled)
if hasCustomerLeft(itemDeliveredOrCustomerLeft) {
// hasCustomerLeft allows us to detect if the promise that resolved first is `customerLeavesCounterPromise` or not
waiter = await callWaiter()
} else {
// An item has arrived
if (waiter) {
deliverItemViaWaiter(itemDeliveredOrVisitorLeft)
} else {
deliverItemAtCounter(itemDeliveredOrVisitorLeft)
}
}
// remove itemDeliveredOrCustomerLeft from allPromisesToBeFulfilled
// END loop
我不确定如何为这种情况实现循环。Promise 必须在解析时累积到队列中,但队列中的特定 Promise 有优先级(超时 Promise 应在到达时尽快执行,但在完成当前 Promise 的处理后,如果 Promise 已经实现正在处理)
解决方案
其中之一必须具有这样的效果,即,无论何时实现,它都应该改变对尚未处理或尚未处理的其他已履行承诺的处理。
你一起运行它们吗?就像是:
promise1 = asyncFunc1()
promise2 = asyncFunc2()
promise3 = asyncFunc3()
Promise.all([promise1, promise2, promise3]).then(//sometthing)
如果是,则无法完成,除非 promise2 函数和 promise3 函数不等待事件、锁或由 promise1 函数处理的东西。
如果是这种情况,最好组织如下承诺:
asyncFunc1()
.then(() => asyncFunc2(paramIfOk))
.catch(() => asyncFunc2(paramIfFail))
在您的示例中:
const allItemsToBeDelivered = [myPromise1(), myPromise2(), ...]
myPromise1() 代码应该等待项目交付并检查是否有人在等待它。这是一个模型/代码设计问题,而不是一个承诺问题。
另一种方法是考虑一些事件驱动的逻辑:实体 Customer 有一个已交付事件的侦听器,该事件将在自身解决之前由 waitItemDelivered() 承诺触发。
编辑:按照这里的要求,对事件驱动的解决方案进行更多详细说明。
简短的回答:这在很大程度上取决于您的软件设计。
它已经发布并在生产中运行?小心这样的变化。如果它是您正在开发的服务,您仍然可以及时考虑一些逻辑更改。不会从根本上改变工作方式但使用事件的解决方案并不是那么好,混合模式永远不会得到长期回报。
例子:
const events = require('events');
class Customer() {
constructor(shop) {
this.emitter = new events.EventEmitter()
this.shopEventListener = shop.emitter
this.setupEventLinstening() // for keeping things clean in the constructor
// other properties here
}
setupEventLinstening() {
this.shopEventListener.on('product-delivered', (eventData) => {
// some logic
})
}
buyProduct() {
// some logic
this.emitter.emit('waiting-delivery', eventData)
}
}
class Shop() {
constructor(shop) {
this.emitter = new events.EventEmitter()
// other properties here
}
addCustomer(customer) {
customer.emitter.on('waiting-delivery', (eventData) => {
// some logic
self.waitDelivery().then(() => self.emitter.emit('product-delivered'))
})
}
waitDelivery() {
return new Promise((resolve, reject) => {
// some logic
resolve()
})
}
}
// setup
const shop = new Shop()
const customer = new Customer(shop)
shop.addCustomer(customer)
这是一种查看逻辑的新方法,但可以在 Promise 中使用类似的方法:
const waitDelivery = () => new Promise((resolve, reject) => {
logisticWaitDelivery().then(() => {
someEmitter.emit('item-delivered')
resolve()
})
}
const customerPromise = () => new Promise((resolve, reject) => {
someListener.on('item-delivered', () => {
resolve()
})
}
promiseAll([waitDelivery, customerPromise])
推荐阅读
- swift - 我需要帮助从 firebase 的快照中获取值
- lambda - 如何在 Java 8 中获取集合中嵌套元素的列表?
- c - TCP 数据报如何到达客户端计算机?
- javascript - R闪亮中的绝对面板隐藏在传单输出后面
- android - Volley 没有通过使用 StringRequest 的 POST 请求将参数附加到我的 url
- tensorflow - ValueError:使用密集层定义稀疏输入时
- javascript - 如何配置 Babel(或 Babel 插件)以自动将目录导入转换为目录内的文件?
- android - react-native: android: exitApp 让进程保持活动状态
- r - R错误中的ltm包
- php - 通过保存/更新时的自定义字段动态更改帖子永久链接