NodeJS 表子项未定义

Posted

技术标签:

【中文标题】NodeJS 表子项未定义【英文标题】:NodeJS table children are undefined 【发布时间】:2020-04-12 07:30:54 【问题描述】:

我一直在研究 discord/roblox 机器人。我已经快完成了,但遇到了一个问题。我是节点的菜鸟,所以如果代码不好,请不要乱说。这样做是我在 roblox 游戏中单击一个按钮,它向 heroku 应用程序发送一个 POST 请求,然后使用提供的信息向我的不和谐服务器中的一个频道发送一条消息。

相关代码:

const Discord = require('discord.js');
const request = require('request');
var express = require('express');
    app = express();
    bodyParser = require('body-parser');
    path = require('path');

var bodyParser = require('body-parser');
var PORT = process.env.PORT || 5000;

const bot = new Discord.Client();

function GetData(id)
    let url = "https://economy.roblox.com/v1/assets/"+id+"/resale-data";
    let url2 = "https://thumbnails.roblox.com/v1/assets?assetIds="+id+"&size=150x150&format=Png";
    let url3 = "http://api.roblox.com/marketplace/productinfo?assetId="+id

    let options = json: true;

    var response = ;

    request(url, options, (error, res, body) => 
        if (error) 
            return console.log(error)
        ;

        if (!error && res.statusCode == 200) 
            response.rap = body.recentAveragePrice
            console.log(response)
        ;
    );

    request(url2, options, (error, res, body) => 
        if (error) 
            return console.log(error)
        ;

        if(!error && res.statusCode == 200) 
            response.thumbnail = body.data[0].imageUrl
            console.log(response)
        
    );

    request(url3, options, (error, res, body) => 
        if (error) 
            return console.log(error)
        ;

        if(!error && res.statusCode == 200) 
            response.name = body.Name
            console.log(response)
        
    );

    return response
;

app.post('/exec', function(req, res) 
    res.setHeader('Content-Type', 'application/json')
    res.send(JSON.stringify(
        success: true
    ));
    console.log("working");
    console.log(req.body)
    var data = GetData(req.body.id)
    if (req.body.state === true)
        var state = "New Projected"
     else 
        var state = "No longer projected"
    
    const msg = new Discord.RichEmbed()
        .setDescription(data.name)
        .setAuthor(state)
        .setColor(0x1c90d9)
        .addField("RAP:", data.rap)
        .setImage(data.thumbnail)
    bot.channels.get("655196831835226133").send(msg);
);

但是,这是在 discord 服务器中发送的消息:

一切都未定义,也没有缩略图

非常感谢您的帮助。非常感谢。

【问题讨论】:

在你做console.log(req.body);的底部附近的输出是什么?如果在创建 msg 之前将 var data 对象记录到控制台,输出是什么? @chrisbyte id: '6789', state: true ,这是我从 Roblox 发送的。这不是我的问题的一部分。另外,data 日志的输出是一个空表?嗯…… @chrisbyte 但是requests 中函数本身的日志返回一个有效的表:name: "Figure1", thumbnail: "long link thing" 基于此,我怀疑GetData 内部的request 调用是异步的,并且在您执行return response 时数据尚不可用。你熟悉 Promisejavascript 中的 async/await 吗? github.com/request/request#promises--asyncawait你需要等待实际数据从请求返回之前你可以继续下一个请求,然后最终返回。 @chrisbyte 不,我不是。你能教我一点吗? 【参考方案1】:

这里有一些阅读:https://www.promisejs.org/

异步函数,如向服务器发出请求,需要时间返回,并在回调中执行此操作。您必须跟踪回调的路径,以确保在上一步完成之前不执行下一步,否则您将完全跳过它。这不像调用一个按顺序做某事的常规函数​​。

当您在GetData 末尾执行return response 时,对象中没有任何内容,因为您需要等待三个响应在各自的回调中完成。您正在看到记录到控制台的事情,因为它们是在后台发生的事实之后发生的。如果您要添加时间戳和额外的日志记录,您会发现这并不是按照您编写它的顺序发生的,而是按照请求本身完成的顺序发生的。

有许多不同的方式来编写和使用 Promise,但这里一种非常简单的方式是嵌套请求,以便它们一个接一个地发生,然后最后 resolve 在你的 @987654325 的最后一个 Promise @object 拥有所有数据。使用 Promises 你resolve 与返回相同,reject 当你想引发错误时。

无需深入探讨,这里有一个示例说明您可以做什么。这是未经测试的,因为我没有运行您的应用程序或尝试重写它,这不是 *** 的用途,但希望它可以向您发送正确的方向。请注意,我在错误上调用 reject 来告诉 Promise 停止运行。

function GetData(id)

  // declare the Promise
  return new Promise((resolve, reject) => 
    let url = "https://economy.roblox.com/v1/assets/"+id+"/resale-data";
    let url2 = "https://thumbnails.roblox.com/v1/assets?assetIds="+id+"&size=150x150&format=Png";
    let url3 = "http://api.roblox.com/marketplace/productinfo?assetId="+id

    let options = json: true;

    var response = ;

    // make request 1
    request(url, options, (error1, res1, body1) => 
        if (error1) 
            console.log(error1)

            // reject
            reject(error1);
        ;

        if (!error1 && res1.statusCode == 200) 

            // all good, continue

            response.rap = body1.recentAveragePrice
            console.log(response)

            // make request 2
            request(url2, options, (error2, res2, body2) => 
              if (error2) 
                console.log(error2)

                // reject
                reject(error2);
              ;

              if(!error2 && res2.statusCode == 200) 

                  // all good, continue

                  response.thumbnail = body2.data[0].imageUrl
                  console.log(response)

                  // make request 3
                  request(url3, options, (error3, res3, body3) => 
                    if (error3) 
                      console.log(error3)

                      // reject
                      reject(error3);
                    ;

                    if(!error3 && res3.statusCode == 200) 
                        response.name = body3.Name
                        console.log(response)

                        // finally, resolve the final response object
                        resolve(response);
                    
                );
              
          );
        ;
    );
  );
;

现在到调用函数。您仍然调用GetData(),但您使用then() 函数来获取已解决的问题,或者使用catch() 来捕获任何错误。我还建议将您的 res.send() 函数放在最后,除非您绝对需要按照最初编写的那样立即返回。

app.post('/exec', function(req, res) 
    res.setHeader('Content-Type', 'application/json')

    console.log("working");
    console.log(req.body)

    // get all the data as a Promise
    GetData(req.body.id)
      .then((data) => 

        // now you have your data!

        if (req.body.state === true)
            var state = "New Projected"
         else 
            var state = "No longer projected"
        
        const msg = new Discord.RichEmbed()
            .setDescription(data.name)
            .setAuthor(state)
            .setColor(0x1c90d9)
            .addField("RAP:", data.rap)
            .setImage(data.thumbnail)
        bot.channels.get("655196831835226133").send(msg);

        res.send(JSON.stringify(
            success: true
        ));
      )
      .catch((err) => 

        // you can handle errors here that were rejected in the promise, if necessary

        res.send(JSON.stringify(
            success: false
        ));

      )
);

【讨论】:

谢谢,但我仍然遇到几乎相同的错误...TypeError: Cannot read property 'Name' of undefined。另外,我确信它存在,因为我之前在输出中看到过它。

以上是关于NodeJS 表子项未定义的主要内容,如果未能解决你的问题,请参考以下文章

Vue组件用作插槽的子项时未定义的属性

显示获取的数据问题:对象作为 React 子项/类型错误无效:未定义

NodeJS - 未捕获的引用错误:未定义原始

nodejs中的自定义mysql函数返回未定义

Nodejs 类返回未定义

ReferenceError:描述未定义NodeJs