1

它是 TypeScript,使用 BlueBird 和 amqplib。我在某处读到只有失败者使用“延迟”,我不想成为失败者(至少出于这个原因)。所以我开始尝试重写这个没有 - 无济于事(只是还没有):

public Request<Rq extends IPublishable, Rs extends IPublishable>(request: Rq): { ackd: Promise<boolean>; response: Promise<Rs> } {
    var ackdPromise: Promise<boolean>;
    var responsePromise: Promise<Rs>;

    var confirmPublish = Promise.promisify(this.ConfirmChannel.publish, this.ConfirmChannel);

    var consumerTag = uuid.v4();
    var responseQueue = Bus.rpcQueueBase + consumerTag;

    var responseDeferred = Promise.defer<Rs>();
    var handleResponse = (msg: IPublishedObj): void => {
        //ack first
        this.ConfirmChannel.ack(msg);
        this.ConfirmChannel.cancel(consumerTag);
        responseDeferred.resolve(Bus.FromSubscription(msg));
    }
    responsePromise = responseDeferred.promise;

    ackdPromise = Promise.resolve(this.ConfirmChannel.assertQueue(responseQueue, { durable: false, exclusive: true, autoDelete: true }))
        .then((okQueueReply) => Promise.resolve(this.ConfirmChannel.consume(responseQueue, handleResponse, { consumerTag: consumerTag })))
        .then((okSubscribeReply) => Promise.resolve(this.ConfirmChannel.assertExchange(Bus.rpcExchange, 'direct', { durable: true, autoDelete: false })))
        .then((okExchangeReply) => confirmPublish(Bus.rpcExchange, request.GetType(), Bus.ToBuffer(request), { type: request.GetType(), replyTo: responseQueue }))
        .then(this.handleAck, this.handleNack)
        .catch((failReason) => {
            console.error(util.format('Error publishing: %s', failReason));
            return false;
        });

    return { ackd: ackdPromise, response: responsePromise };
}

我已经转换了所有类似的方法并在此进行了一些运行,但总是不够用。也许是因为我正在尝试返回两个值(确认承诺和响应承诺),但实际上我认为这与尝试为调用嵌入式处理程序的最终结果返回承诺有关 - 不使用延迟。

你能(请)做得更好(或告诉我推迟是可以的)吗?

4

1 回答 1

1

以下行接受一个回调并返回一个承诺:

.then((okQueueReply) => Promise.resolve(this.ConfirmChannel.consume(responseQueue, handleResponse, { consumerTag: consumerTag })))

相反,只需从它返回一个承诺就足够了,所以它变成:

.then((okQueueReply) => Promise.resolve(this.ConfirmChannel.consume(responseQueue, { consumerTag: consumerTag })))

当我们在那里时, Promise.resolve 在.then处理程序内部是多余的,因为它们已经吸收了 Promise。此外,解决 okSubscribedReply方法只有在有意义的情况下才是好的,否则你知道事情进展顺利,因为承诺没有拒绝。所以最好返回有意义的数据。

由于承诺链可以轻松分支,这将使您的代码类似于:

var queueSet = { durable: false, exclusive: true, autoDelete: true };
var tag = { consumerTag: consumerTag };
var channel = Promise.resolve(this.ConfirmChannel.assertQueue(responseQueue, queueSet))
             .then((okQueueReply) => this.ConfirmChannel.consume(responseQueue, tag));

var responsePromise = channel.then((msg) => {
    this.ConfirmChannel.ack(msg); // I don't like this, but ok.
    this.ConfirmChannel.cancel(consumerTag);
    return Bus.FromSubscription(msg);
});

所以,我们responsePromise做同样的事情,但现在不需要延迟,因为ackdPromise我们可以简单地从通道链接它。

var exchangeSet = { durable: true, autoDelete: false };
var ackdPromise = channel.then(() => this.ConfirmChannel.assertExchange(Bus.rpcExchange, 'direct', exchangeSet)).then(....);

由于您一直在使用.ConfirmChannel而不是this直接使用,我们可以利用.bind并执行以下操作:

 var assertSettings = { durable: false, exclusive: true, autoDelete: true };
 var p = Promise.bind(this.ConfirmChannel)
                .then(() => this.assertQueue(responseQueue, assertSettings))
                .then(() => this.consume(responseQueue, {consumerTag: consumerTag}));

 var responsePromise = p.then((msg) => {
     this.ack(msg);
     this.cacnel(consumerTag);
     return Bus.FromSubscription(msg);
 });

 var exSet = { durable: true, autoDelete: false };
 var pubSet = { type: request.GetType(), replyTo: responseQueue };
 var ackdPromise = p.then(() => assertExchange(Bus.rpcExchange, 'direct', exSet))
                    .then(() => confirmPublish(Bus.rpcExchange, 
                                               request.GetType(), 
                                               Bus.ToBuffer(request), pubSet))
                    .then(this.handleAck, this.handleNack)
                    .catch(function(err){
                         console.error(util.format('Error publishing: %s', failReason));
                          return false;
                    });
 return { ackd: ackdPromise, response: responsePromise };
于 2014-05-24T09:16:54.677 回答