解决JS中的异步生产者-消费者问题

时间:2019-06-27 04:59:36

标签: javascript node.js ecmascript-6

我有一个数据生产者和一个数据消费者。生产者异步生产,而我又希望消费者在有数据需要消费时异步消费。

我立即想解决这个问题的方法是使用一些等待转移/获取much like this async queue in the python standard

的队列对象。

但是,我进行了搜索,但找不到任何具有这种数据结构供我使用的JS库。我本以为这将是一种常见的模式。

在JS中解决此问题的常用模式是什么?有没有什么库可以帮助您?

3 个答案:

答案 0 :(得分:2)

如果数据的生产者只是自发地生产数据,而消费者只是想知道什么时候有新数据,那么这听起来像消费者应该订阅一个事件,只要有新数据就将触发该事件。您可以只使用node.js中的EventEmitter对象创建一个发射器,供使用者使用,生产者将在有新数据时触发并进行事件。无需外部库即可实现此功能,因为内置的EventEmitter对象具有注册通知和触发通知所需的所有工具。

如果数据的使用者请求数据,然后生产者去异步获取它,那么这只是典型的异步API。该API可能应该返回一个诺言,并且生产者将在准备好新数据后用新数据来解决诺言,或者如果检索数据时出错则拒绝它。

通过您提供的一些描述,我看不到对复杂的排队系统的任何特殊需求。这听起来像是发布/订阅或简单的事件通知系统。如果问题更复杂,请向我们提供有关数据生成器的更多详细信息,以便我们可以更好地将node.js中可用的工具与您特定问题的需求进行匹配。

答案 1 :(得分:0)

如果是简单的小型程序,我只是简单地编写如下内容。

var data = [];

function Consumer()
{
    this.isConsuming = false;

    this.notify = function(){
        if(this.isConsuming)
        {
            return;
        }
        this.consumeNext();
    }

    this.consumeNext = async function(){
        this.isConsuming = true;
        if(data.length > 0)
        {
            //consume one datum
            console.log(await this.consume(data.shift()));

            //consume next datum
            this.consumeNext();
        }
        else
        {
            this.isConsuming = false;
        }
    }

    this.consume = async function(datum){
        return datum * datum;
    }
}



var consumer = new Consumer();
//call consumer.notify() when your producer produces
data.push(1,2,3,4,5);
consumer.notify();

答案 2 :(得分:0)

这会给你另一个想法。在我的场景中,生产者每 1000 毫秒创建一次数据,消费者等待直到生产者创建新数据并解决其承诺。

let dataArray = []
let consumerResolver = null

function producer() {
    setInterval(() => {
        const newData = "my new Data"
        dataArray.push(newData)

        if (consumerResolver) {
            consumerResolver()
        }
    }, 1000);
}

async function consumer() {
    while (true) {
        if (dataArray.length === 0) {
            const producerPromise = new Promise((resolve) => {
                consumerResolver = resolve
            })
            await producerPromise
        }

        consumerResolver = null
        const data = dataArray.shift()
        console.log(data)
    }
}