如何在 NodeJS Express 应用程序的其他地方使用连接

How to use a connection elsewhere in NodeJS Express app

我到处搜索,但找不到解决我问题的好方法( 我认为更..通用..我想了解如何以及为什么)。 我正在使用 google pubsub,我的项目中有一项服务。它有两个功能。我需要 app.js 中的文件并收听。但是我怎样才能在应用程序的其他地方收听呢?就像在控制器中说的那样?这是 messageService.ts 代码:

require('dotenv').config();
const {PubSub} = require('@google-cloud/pubsub');

let messageCount = 0;

let projectId = 'xxx';
let topicName = 'xxxt';
let subscriptionName = 'xxx';

// Instantiates a client
const pubsub = new PubSub({projectId});

// Creates a new topic
const topic = pubsub.topic(topicName);

const subscription = topic.subscription(subscriptionName);
module.exports = {
    listenForMessages : () => {
        const messageHandler = message => {
            console.log(`Received message ${message.id}:`);
            console.log(`\tAgresso Data: ${message.data}`);
            //console.log(`\tAttributes: ${message.attributes}`);
            messageCount += 1;
            message.ack();
        };
        
        subscription.on('message', messageHandler);
    },
    sendTestMessage : () => {
        let messageObject = {
            action: 'insert',
            objectType: 'resource',
            objectId: 12456,
            stamp: Date.now()
        }
    
        topic.publish(Buffer.from(JSON.stringify(messageObject)));
        console.log('sent test message') ;
    }

}

您的 subscription 常量未必只能在此文件中使用。

我建议你换一个 approach/architecture。一个是你有一个名为 PubSubConnection.ts 的文件,你可以在其中进行整个 PubSub/topic/subscription 实例化并在整个项目中共享它。这样您就不必在每次要使用新主题时都重新创建它。甚至可以分解为任何主题。

示例:

app.ts

import dotenv from 'dotenv';
dotenv.config();
import { PubSub } from '@google-cloud/pubsub';
import express from 'express';
import PubSubConnection from "./PubSubConnection";
import { sendTestMessage } from './listenSub';

const app = express();

// DI (dependency injection)
// Create a one time pubsub as you will certainly only use the same project_id across your app
const pubSub = new PubSub({ projectId: process.env.PROJECT_ID });
// Create the connection to the topic/subscription dynamically here or anywhere else
// in your di where your service/component need an access to a special topic/subscription
const pubSubConnection = new PubSubConnection(pubSub, 'your_topic_name', 'your_sub_name');

// this members could be passed to any services that your app runs
const topic = pubSubConnection.getTopic;
const subscription = pubSubConnection.getSubscription;

// And use as many function anywhere you need it 
// by just passing it the already created topic/subscription
sendTestMessage(topic);

app.listen(process.env.PORT, () => {
    console.log('Server started');
});

PubSubConnection.ts

// Dotenv should always be loaded first in your application (aka app.js in your case) and in the 1st line
// because it only need to be loaded 1 time for the env variable to be accessible
// there is no neeed to load it everywhere you need to access env var
// require('dotenv').config();

import { PubSub, Subscription, Topic } from '@google-cloud/pubsub';

export default class TopicSubConnection {
    topic: Topic
    subscription: Subscription

    constructor(
        private readonly pubSub: PubSub, 
        private readonly topicName: string, 
        private readonly subscriptionName: string
    ) {
        this.topic = new Topic(this.pubSub, this.topicName);
        this.subscription = new Subscription(this.pubSub, this.subscriptionName);
    }
  
    public get getTopic(): Topic {
        return this.topic;
    }
  
    public get getSubscription(): Subscription {
        return this.subscription;
    }
}

subOperations.ts

import { Subscription, Topic, Message } from "@google-cloud/pubsub";

let messageCount = 0;

export const listenForMessages = (subscription: Subscription): void => {
    const messageHandler = (message: Message) => {
        console.log(`Received message ${message.id}:`);
        console.log(`\tAgresso Data: ${message.data}`);
        //console.log(`\tAttributes: ${message.attributes}`);
        messageCount += 1;
        message.ack();
    };
    
    // the handler could be an array of functions, this means you could have different
    // functions listening to the same subscription
    subscription.on('message', messageHandler);
};

export const sendTestMessage = (topic: Topic): void => {
    let messageObject = {
        action: 'insert',
        objectType: 'resource',
        objectId: 12456,
        stamp: Date.now()
    }

    topic.publish(Buffer.from(JSON.stringify(messageObject)));
    console.log('sent test message') 
};