【问题标题】:Google Cloud Pub/Sub Node.js Sample: TypeError: Cannot read property 'on' of nullGoogle Cloud Pub/Sub Node.js 示例:TypeError:无法读取 null 的属性“on”
【发布时间】:2016-01-27 07:38:43
【问题描述】:

我正在使用 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 来做同样的事情。

这篇文章可能是相关的。 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. 执行“节点 pubsub.js”
  2. 我可以看到示例消息“新消息!”

【问题讨论】:

  • 在使用subscription 之前,subscribe() 回调当前不检查err 参数。我敢打赌,err 告诉你,出了什么问题。
  • @Sirko 感谢您的回复。我仍然不确定下一步该怎么做...您能给我更多建议吗..
  • 很抱歉我删除了标签。
  • 非常感谢。只是想确保您在任何事情上都不需要我们的帮助。干杯。

标签: google-cloud-messaging google-compute-engine publish-subscribe google-cloud-platform


【解决方案1】:

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

基于 PubSub index.js source codePubSub.prototype.subscribe() 发出 HTTP 请求以创建符合 projects.subscriptions.create API 格式的新订阅。如果响应返回 409 ALREADY_EXISTS 错误并且您尚未将 options.reuseExisting 设置为 true,则您提供的回调将被调用并显示错误并将 null 作为订阅。根据options.reuseExistingtopic.subscribe 的PubSub Nodejs 文档,如果未指定,则默认值为false

如果为 false,则尝试创建已存在的订阅将 失败。

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

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 等方法是否检查主题是否存在、是否存在订阅、创建新订阅或获取现有订阅。我只是警告添加健壮的错误处理。

【讨论】:

【解决方案2】:

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

// 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

});

【讨论】:

  • 谢谢。我试过了,但显示了同样的错误。我认为订阅为空是有问题的。
  • @zono 所以err 也为空?
  • 如果我设置“不存在订阅密钥”没有错误。如果我设置了“现有订阅密钥”,则会显示错误。当我调试 gcloud JS 时,错误显示“您设置了现有资源..”我认为订阅是可以的。然后我打开另一个终端并发布到同一主题。但是什么都没有发生...我可能必须知道数据拉取或更改为推送类型(将特定 URL 设置为 webhook...)
  • 公认的答案是正确的——但对于那些刚从 PubSub 开始的人:还要立即检查 err 参数——即如果您还没有激活 API 权限,它将被设置(同时永远不会触发 onError
猜你喜欢
  • 2015-08-21
  • 2021-11-08
  • 2023-03-22
  • 1970-01-01
  • 2020-01-29
  • 2017-11-13
  • 2022-01-13
  • 1970-01-01
  • 2022-01-12
相关资源
最近更新 更多