Google Cloud Pub/Sub Node.js Sample: TypeError: Cannot read property 'on' of null

Google Cloud Pub/Sub Node.js Sample: TypeError: Cannot read property 'on' of null

我正在使用 GCP,我想使用 Cloud Pub/Sub。当我尝试 Node.js 示例时,我在下面遇到了这个错误。有谁知道如何解决它?

/private/tmp/pubsub/pubsubsample.js:26
  subscription.on('error', onError);
              ^

TypeError: Cannot read property 'on' of null
    at /private/tmp/pubsub/pubsubsample.js:26:15
    at /private/tmp/pubsub/node_modules/gcloud/lib/pubsub/index.js:474:7
    at Object.handleResp (/private/tmp/pubsub/node_modules/gcloud/lib/common/util.js:113:3)
    at /private/tmp/pubsub/node_modules/gcloud/lib/common/util.js:422:12
    at Request.onResponse [as _callback] (/private/tmp/pubsub/node_modules/gcloud/node_modules/retry-request/index.js:106:7)
    at Request.self.callback (/private/tmp/pubsub/node_modules/gcloud/node_modules/request/request.js:198:22)
    at emitTwo (events.js:87:13)
    at Request.emit (events.js:172:7)
    at Request.<anonymous> (/private/tmp/pubsub/node_modules/gcloud/node_modules/request/request.js:1035:10)
    at emitOne (events.js:82:20)

https://github.com/GoogleCloudPlatform/gcloud-node

var gcloud = require('gcloud');

// Authenticating on a per-API-basis. You don't need to do this if you
// auth on a global basis (see Authentication section above).

var pubsub = gcloud.pubsub({
  projectId: 'xxxxx',
  keyFilename: 'xxx.json'
});

// Reference a topic that has been previously created.
var topic = pubsub.topic('info');

// Publish a message to the topic.
topic.publish({
  data: 'New message!'
}, function(err) {});

// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
  // Register listeners to start pulling for messages.
  function onError(err) {}
  function onMessage(message) {}
  subscription.on('error', onError);
  subscription.on('message', onMessage);

  // Remove listeners to stop pulling for messages.
  subscription.removeListener('message', onMessage);
  subscription.removeListener('error', onError);
});

...我现在正在使用 PubSub,但我在想我是否可以通过使用 Google Cloud PubSub 来做同样的事情。

这 post 可能是相关的。 Node.js on Google Cloud Platform Pub/Sub tutorial worker is failing with "TypeError: Cannot call method 'on' of null"


更新 1

我更改为此代码但显示相同的错误。

(错误)

subscription.on('error', onError);
            ^
TypeError: Cannot read property 'on' of null

(代码)

// Subscribe to the topic
topic.subscribe('new-subscription', function(err, subscription) {
  if( err ) {
    // something went wrong, react!
    return;
  }

  // Register listeners to start pulling for messages.
  function onError(err) {}
  function onMessage(message) {}
  subscription.on('error', onError);
  subscription.on('message', onMessage);

  // Remove listeners to stop pulling for messages.
  subscription.removeListener('message', onMessage);
  subscription.removeListener('error', onError);
});

更新 2

我的期望是下面这个。

  1. 执行"node pubsub.js"
  2. 我可以看到示例消息 'New message!'

目前您在订阅时不检查错误,而只是在订阅时检查错误。要改变它,你可以使用这样的东西:

// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {

  // first check for errors
  if( err ) {
    // something went wrong, react!
    return;
  }

  // rest of your code

});

当调用 topic.subscribe() 时,该方法本质上是调用 pubsub.subscribe() 方法,并将特定的 Topic 实例作为其上下文。这从Topic.prototype.subscribe下的source code就可以看出。

基于options.reuseExisting下的PubSub index.js source code, PubSub.prototype.subscribe() issues a HTTP request to create a new subscription respecting the projects.subscriptions.create API format. If the response returns a 409 ALREADY_EXISTS error and you have not set the options.reuseExisting to true, the callback you provided will be invoked with the error and null as a subscription. According to the PubSub Nodejs documentation for topic.subscribe,不指定默认值为false

If false, attempting to create a subscription that already exists will fail.

为了更有效地使用此设计,我建议如下:

var pubsub = require('gcloud').pubsub({
    "projectId" : "project-id",
    "keyFilename" : "key-file.json"
});

// This topic should already have been created
var topic = pubsub.topic("interesting-topic");

// The message that will be published
var message = {"data": "Welcome to this interesting thread"};

// Callback to throw an exception if publish was unsuccessful
// Will log published message IDs if successful
function publishedHandler(err, messageIds, responseBody) {
    if (err) {
        // Could not publish message(s)
        throw err;
    }
    console.log(messagesIds);
}

// Callback to throw an exception if a subscription could not be found or created
// Will attach event listeners if successfully gets a subscription
function subscriptionHandler(err, subscription, responseBody) {
    if (err) {
        // Could not get or create a new subscription
        throw err;
    }
    subscription.on("error", errorHandler);
    subscription.on("message", messageHandler);
}

// Publish a message to the topic
topic.publish(message, publishedHandler);

// Create or get 'sub' and subcribe it to 'interesting-topic'
topic.subscribe("sub", {"reuseExisting": true}, subscriptionHandler);

Issue 696 可能并未准确提及此问题,但确实讨论了在为 Cloud PubSub 设计 Node.js 库时所做的一些语义选择。尚不完全清楚 topic.publishtopic.subscribe 之类的方法是否检查主题是否存在、订阅是否存在、创建新订阅或获取现有订阅。我只是警告添加强大的错误处理。