如何在需要解决之前触发Promise中的处理,比如java Future?

时间:2016-02-13 07:39:54

标签: javascript node.js promise mocha

我有一个用Mocha编写的集成测试,需要在其他事情发生之前注册一个监听器,否则我最终会遇到竞争条件。

基本上,我正在向某个HTTP服务器发送一个帖子,然后期待来自Kafka消息服务的回调,其中包含我需要检查其值的一些消息。 (http服务器的帖子将消息放在kafka上)。

我的最初晋级以竞争状态结束。

var request = require("supertest-as-promised");
var Promise = require("bluebird");

beforeEach() { //set up kafka connection and kafkaConsumer ... }
describe('send-status', function statusSend() {
    it("sends a post to the server and gets a message on kafka", function (done) {
           request('http://myserver:8080')
                    .post('/myendpoint')
                    .type('json')
                    .send(stuff)
                    .expect(200)
            })
            .then(function () {
                //todo:  antipattern - can be replaced with a custom promisfier.
                return new Promise(function (resolve, reject) {
                    kafkaConsumer.on('message', function (message) {
                            resolve(message)
                        })
                        //and reject cases
                });
            })
            .then(function (message) {
                //check message
                done()
             })
            .catch() ...

问题当然是kafka消息可以在帖子之后立即被解雇,但在第二个promise之前可以注册kafkaConsumer.on('message')监听器。

所以我需要在链中开始发布请求承诺之前注册kafkaConsumer.on('message')

这是我对节点和承诺的了解。如果这是Java,我创建一个Callable来启动监听器(并且可能有一个等待,直到它在我的帖子之前开始),把它扔到执行器上并稍后使用它 - 这个值要么已经是那里或者未来会等待它。

有了承诺,我不会理解如何在链中调用then()之前启动kafkaConsumer.on('message')

我尝试过类似的东西,但它很难看,但仍会导致竞争条件:

function foo(message) {
    return new Promise(function (resolve, reject) {
        resolve(message);
    });
}
describe(...)
    it("sends post to ...", function(done) {
        var onMessagePromise;
        kafkaConsumer.on('message', function (message) {
            onMessagePromise = foo(message)
        });

        request()
        .then(function () {
            return onMessagePromise;
        })
        .then ...

我的另一个想法是在执行请求之前先监听消息,将其分配给变量,然后让承诺解析该变量......但如果消息在消息之后发生则不会起作用承诺被退回,善良的失败点。我能想到的一切都会导致竞争状态。

1 个答案:

答案 0 :(得分:1)

  

所以我需要在链中开始发布请求承诺之前注册kafkaConsumer.on('message')

你可以这样做,从你的解释来看,它听起来与在Java中解决它的方式非常相似(虽然我对Java不太了解,所以我确信它会一些差异):

var kafkaPromise = new Promise(function (resolve, reject) {
  kafkaConsumer.on('message', function (message) {
    resolve(message);
  })
  //and reject cases
});

request('http://myserver:8080')
        .post('/myendpoint')
        .type('json')
        .send(stuff)
        .expect(200)
        .then(function() {
          return kafkaPromise;
        })
        .then(...)
        .catch(...);

如果kafkaPromise已解决,将使用其值;如果它仍处于未决状态,链将等到它被解决(或拒绝)之后再继续。