带有 Q 承诺的递归



我有一个递归与承诺发生的情况,我需要一些帮助。

我有一个包含一系列消息的数组。每条消息可以是:1 个基元,如字符串;或 2 复合,它只是一个指向包含消息序列的数据库区域的指针。例如,数组可以是:['hello', (compound), 'there'],其中(复合)可以包含从数据库获取复合消息时的['how', 'are', 'you']。因此,最终的"扩展"数组如下所示:['hello', 'how', 'are', 'you', 'there']。将消息数组完全转换为原始消息数组称为"扩展"。

请注意,复合消息中的消息也可以是复合消息,这就是递归的用武之地。例如,如果上面例子中的(化合物)是['how', 'are', 'you', (lower level compound)]的,而(较低级别的复合)是['Tom', 'Jerry']的,那么(化合物)将被扩展为['how', 'are', 'you', 'Tom', 'Jerry'],而原始数组将被扩展为['hello', 'how', 'are', 'you', 'Tom', 'Jerry', 'there']

这是我认为代码的样子,没有承诺:

function expandMessages(messages, outputMessages) {
messages.forEach(function(message) {
if (message.primitive) {
outputMessages.push(message);
}
else {
var fetchedMessages = fetchMessages(message);
expandMessages(fetchedMessages, outputMessages);
}
});
}

在上面的代码中,fetchMessages从数据库获取复合消息的消息。

我应该如何承诺上面的代码,以便在外部承诺返回后:1 outputMessages 只包含原始消息;并保持 2 正确的消息顺序,即任何复合消息的"子消息"都插入到复合消息在原始数组中的位置。

谢谢!

涉及承诺的唯一原因是当fetchMessages()是异步的时,所以让我们假设是这样。

代码出奇地简单:

function expandMessages(messages) {
return Q.all([].concat(messages).map(function(m) {
return Array.isArray(m) ? fetchMessages(m).then(expandMessages) : m.then ? m.then(expandMessages) : m;
})).then(flatten);
}

其中flatten()是:

function flatten(list) {
return list.reduce(function(a, b) {
return a.concat(Array.isArray(b) ? flatten(b) : b);
}, []);
};

演示

解释

  • [].concat(messages)是一种安全措施,以防止messages不是阵列,在这种情况下,messages.map()会抛出。
  • .map(...)将字符串/数组/承诺的混合数组映射到字符串和承诺的混合数组。
  • m.then(expandMessages)fetchMessages(m).then(expandMessages)会导致递归发生。
  • Q.all()聚合字符串和承诺的混合数组,并提供字符串和数组的混合数组。
  • .then(flatten)将字符串和数组的混合数组减少为字符串数组。
  • 最终数组的顺序是您想要的,因为Q.all(messages.map(...))(在每个级别)提供一个与messages一致的数组。
  • 正如您将在演示中看到的那样,"复合消息"可以是 Array 或 promise 包装的 Array,这提供了您可能需要也可能不需要的一定程度的灵活性(但它是免费的)。

相关内容

  • 没有找到相关文章

最新更新