【问题标题】:How do I transfer data from one method to another in Node.js?如何在 Node.js 中将数据从一种方法传输到另一种方法?
【发布时间】:2018-10-15 21:11:36
【问题描述】:

我正在使用 Telegram 机器人 API 和 AWS S3 从存储桶中读取数据。我需要在Telgraf方法中使用来自s3方法的数据,但我不知道如何:

'use strict'

const Telegraf = require('telegraf');
const bot = new Telegraf('TOKEN')

var AWS = require('aws-sdk')
var s3 = new AWS.S3({
    accessKeyId: 'key',
    secretAccessKey: 'secret'
}) 

var params = {Bucket: 'myBucket', Key:"ipsum.txt"};

var s3Promise = s3.getObject(params, function(err, data) {
    if (err) console.log(err, err.stack);
    else              
    var words= data.Body.toString(); //WHAT I WANT IN IN COMMAND METHOD
    console.log('\n' + words+ '\n') //Returns ipsum.txt as string on console
})

bot.command('s', (ctx) => { //Bot Command
    s3Promise; //Returns ipsum.txt as string on console
    ctx.reply('Check console') //Meesage in Telegram
    //ctx.reply(<I WANT data.Body.toSting() HERE>)
});

const { PORT = 3000 } = process.env
bot.startWebhook('/', null, PORT)

如何在 ctx.reply() 中使用 s3.getObject 方法中的数据?

【问题讨论】:

  • 在 s3.getObject 中调用 bot.command
  • 成功了!如果我想作为文件而不是字符串接收,我需要使用什么 s3 方法?
  • 我对s3一无所知,抱歉
  • @Diego 您要将文件作为电报的附件发送吗?
  • @Diego 你试过从响应中制作一个 Blob 吗?

标签: javascript node.js amazon-web-services amazon-s3 telegram


【解决方案1】:

如果您想将文件作为附件发送,您必须使用:ctx.replyWithDocument。除此之外,您的问题是:How do I return the response from an asynchronous call?

在这种特殊情况下,您可以使用 s3.getObject(params).promise() 以避免回调 API,并在您的 bot.command 侦听器中轻松使用它。

使用async/await (Node >= 7.6) 你的代码可以这样写

'use strict';

const Telegraf = require('telegraf');
const bot = new Telegraf('TOKEN');

const AWS = require('aws-sdk');
const s3 = new AWS.S3({
    accessKeyId: 'key',
    secretAccessKey: 'secret'
});

const params = {
    Bucket: 'myBucket',
    Key: 'ipsum.txt'
};

bot.command('s', async ctx => { // Bot Command

    try {

        // If you're sending always the same file and it won't change
        // too much, you can cache it to avoid the external call everytime
        const data = await s3.getObject(params).promise();

        ctx.reply('Check console'); // Message in Telegram

        // This will send the file as an attachment
        ctx.replyWithDocument({
            source: data.Body,
            filename: params.Key
        });

        // or just as text
        ctx.reply(data.Body.toString());

    } catch(e) {
        // S3 failed
        ctx.reply('Oops');
        console.log(e);
    }
});

const {
    PORT = 3000
} = process.env;

bot.startWebhook('/', null, PORT);

有关如何处理文件的更多信息,请访问telegraf docs

PS:我测试了代码,它可以正常工作:

【讨论】:

  • ctx.reply(data.Body.toString());工作正常,但 replyWithDocument() 没有。可能是因为source: 是指示路径而您要放置缓冲区?我得到 throw er; // 未处理的“错误”事件错误:在控制台结束后写入。在管理控制台中,我看到我的 lambda 函数正在使用 Node.js 8.10。
  • source 采用 Buffer、文件路径、Url、Buffer 或 ReadStream。查看文档:telegraf.js.org/#/?id=working-with-files。您可以发布完整的堆栈跟踪吗?一个 pastebin 就可以了。
  • 我在本地测试代码,replyWithDocument 完美运行。自己试试。您可以使用startPolling 代替startWebook 进行本地测试。
  • 我之前试过很多次。无论如何,我尝试通过使用apex up 进行部署来使其工作,我得到this error。您的代码在本地工作,但我在部署它时遇到同样的错误。另外,我涵盖了 IP,我是一个爱好者,我不知道我是否应该将它留在 pastebin 中。
  • 该问题与当前问题无关。您应该提出一个新问题,以便其他人可以帮助您。你提出新问题后,我会看看它。
【解决方案2】:

虽然我没有使用过 S3,但我知道 AWS 服务在其实现中添加了对 Promises 的支持以避免使用回调。就个人而言,我更喜欢使用 Promise,因为我认为它们会带来更易读的代码。

我认为以下内容应该可以解决您遇到的问题。

'use strict'

const Telegraf = require('telegraf');
const bot = new Telegraf('TOKEN')

var AWS = require('aws-sdk')
var s3 = new AWS.S3({
    accessKeyId: 'key',
    secretAccessKey: 'secret'
}) 

var params = {Bucket: 'myBucket', Key:"ipsum.txt"};

bot.command('s', (ctx) => {
  s3.getObject(params).promise()
  .then(data => {
    ctx.reply('Check console');
    ctx.reply(data.Body.toString());
  }, err => console.log(err, err.stack));
})

const { PORT = 3000 } = process.env
bot.startWebhook('/', null, PORT)

【讨论】:

  • 那行不通。我在控制台中没有看到任何错误,但什么也没发生。
  • 我不熟悉 Telegraf,所以我猜这个问题与没有正确调用它的命令有关。我很抱歉。看起来马科斯确实在同一条轨道上,但更了解 Telegraf 以及如何做你想做的确切事情。
【解决方案3】:

按照Luca 的建议,我在 s3.getObject 中调用了 bot.command,它可以正常工作!

s3.getObject(params, function(err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else              
        bot.command('s', (ctx) => {
            ctx.reply('Succesfully read from S3:\n\n' + data.Body.toString())
        });
    })

【讨论】:

  • 你应该检查我的答案,在 s3 回调中设置你的 bot.command 是不好的做法,它应该是相反的
猜你喜欢
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 2014-02-24
  • 2018-03-10
  • 1970-01-01
相关资源
最近更新 更多