【发布时间】:2016-09-10 05:53:56
【问题描述】:
简短的问题,相当抽象:
Process A 和 process B 都返回承诺。
进程B 需要调用进程A 零次或多次来解决其承诺。这种事情的正确模式是什么?
更长但更具体的问题:
想象一下,我有一个produceMsg 进程,它创建了一个承诺,当它被解决时,会产生一个 n 字节的缓冲区。 (也许它正在通过网络连接获取字节。也许偶尔会产生错误。)这是一个测试夹具:
// promise to yield a buffer of up to 20 bytes and an occasional error
function produceMsg() {
return new Promise(function(resolve, reject) {
var n = Math.floor(Math.random() * 20);
if (n === 0) { // generate an error sometimes...
reject("some error");
} else { // create a buffer with n random bytes
var msg = createRandomMessage(n);
console.log('generating', msg);
resolve(msg);
}
});
};
// helper method: create a buffer of n random bytes
function createRandomMessage(n) {
return Buffer(Array(n).fill().map(function(e) {
return Math.floor(Math.random() * 256); }));
}
现在想象我有一个方法来consume 那些承诺:
function consume() {
setInterval(function() {
produceMsg()
.then(function(b) { console.log("==> fetched", b); })
.catch(function(b) { console.log("==> error", b); })
;
}, 200);
}
测试它,它按预期工作:
generating <Buffer c8 71 6a 3f fe 84 05 71>
==> fetched <Buffer c8 71 6a 3f fe 84 05 71>
generating <Buffer 03 66>
==> fetched <Buffer 03 66>
==> error some error
generating <Buffer 49 d2 4f 6f d6 bc 48 cf e7 db f7 f6 f7 e2 e7 5c df>
==> fetched <Buffer 49 d2 4f 6f d6 bc 48 cf e7 db f7 f6 f7 e2 e7 5c df>
generating <Buffer ef 6c 5f 3c 2f c8 b1 ff b5 eb 13 0e 76 d8>
==> fetched <Buffer ef 6c 5f 3c 2f c8 b1 ff b5 eb 13 0e 76 d8>
但是现在我被告知我必须将传入的数据包重新构建为 10 字节的块。 (好吧,这是一个人为的例子,但我确实必须重新构建数据包。)
所以我需要一个中间 reframer 对象,它创建一个承诺,在它解析时返回十字节数据包。如果它没有十个字节,它需要从produceMsg 进程中收集字节,直到它积累足够多。
我修改后的consume 方法可能如下所示:
function consume() {
var reframer = new Reframer(produceMsg);
setInterval(function() {
reframer.read()
.then(function(b) { console.log("==> fetched", b); })
.catch(function(b) { console.log("==> error", b); })
;
}, 200);
}
...并使用与上面相同的数据,我希望输出如下所示:
generating <Buffer c8 71 6a 3f fe 84 05 71>
generating <Buffer 03 66>
=> fetched <Buffer c8 71 6a 3f fe 84 05 71 03 66>
=> error some error
generating <Buffer 49 d2 4f 6f d6 bc 48 cf e7 db f7 f6 f7 e2 e7 5c df>
=> fetched <Buffer 49 d2 4f 6f d6 bc 48 cf e7 db>
generating <Buffer ef 6c 5f 3c 2f c8 b1 ff b5 eb 13 0e 76 d8>
=> fetched <Buffer f7 f6 f7 e2 e7 5c df ef 6c 5f>
=> fetched <Buffer 3c 2f c8 b1 ff b5 eb 13 0e 76>
(注意最后两行reframer 产生了两条消息,但没有调用produceMsg,因为它已经积累了足够的字节。)
问题:reframer.read() 的结构是什么?
我还没有弄清楚如何构建reframer.read() 方法的内部结构。有没有一种很好的模式来做这种事情,其中一个承诺有条件地将调用链接到零个或多个承诺?
(注意:我不是询问如何使用 concat 和 slice 缓冲区等等——我已经有代码可以做到这一点。我坚持的是控制Promises的生成和解析流程。)
【问题讨论】:
-
你似乎在寻找递归。
-
@Bergi 好吧,伪递归...
标签: javascript node.js promise