【问题标题】:TypeError: Cannot read property 'method' of undefinedTypeError:无法读取未定义的属性“方法”
【发布时间】:2019-07-13 11:59:17
【问题描述】:

当尝试为我们获得的方法运行 RPC 命令时,我似乎无法找出问题所在。它在本地工作,但不在实时 linux 服务器上。

TypeError:无法读取未定义的属性“方法” C:\ssc-exchange-transactions\app.js:23:13 at Layer.handle [as 处理请求] (C:\ssc-exchange-transactions\node_modules\express\lib\router\layer.js:95:5) 接下来 (C:\ssc-exchange-tranactions\node_modules\express\lib\router\route.js:137:13) 在 Route.dispatch (C:\ssc-exchange-transactions\node_modules\express\lib\router\route.js:112:3) 在 Layer.handle [as handle_request] (C:\ssc-exchange-transactions\node_modules\express\lib\router\layer.js:95:5) 在 C:\ssc-exchange-transactions\node_modules\express\lib\router\index.js:281:22 在 Function.process_params (C:\ssc-exchange-transactions\node_modules\express\lib\router\index.js:335:12) 在下一个 (C:\ssc-exchange-tranactions\node_modules\express\lib\router\index.js:275:10) 在 jsonParser (C:\ssc-exchange-transactions\node_modules\body-parser\lib\types\json.js:119:7) 在 Layer.handle [as handle_request] (C:\ssc-exchange-transactions\node_modules\express\lib\router\layer.js:95:5)

const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const port = 5000;
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const dsteem = require('dsteem');
const client = new dsteem.Client('https://api.site.com');
app.set('trust proxy', true);
app.disable('x-powered-by');


app.post('/', function(req,res){
    try
    {
    var body=JSON.parse(req.body.curl);
    }
    catch(err)
    {
     res.send({msg: 'invalid command', error: err});
    }
    if(body.method !=undefined && body.method == "POST")
    {
    let options = {
      url:body.url,
      method:body.method,
      headers:body.headers,
      body: JSON.stringify(body.body)
    };
    request(options, (error, response, body) => {
      if (error) {
        console.error("An error has occurred: ", error);
        res.send(error);
      }
      else {
        let responseData = JSON.parse(body);
        res.send(responseData);
      }
    });
  }
  ///Ends if
  else if(body.method != undefined && body.method == "GET")
  {
    let options = {
    //   url: body.url+'?account='+body.body.params.account+'&limit='+body.body.params.limit+
    //   '&offset='+body.body.params.offset+'&&symbol='+body.body.params.symbol,
         url: 'https://api.site.com/accounts/history'+body.symbol,
         method: "GET",
         headers: {"Content-type": "application/json"},
    };
    request(options, (error, response, body) => {
      if (error) {
        console.error("An error has occurred: ", error);
        res.send(error);
      }
      else {
         var withdraw = [], deposit = [];
         body= JSON.parse(body);
         body.forEach(el => {
           if(el.from == "account"){
            delete el.block;
            delete el.symbol;
            delete el.from_type;
            delete el.to_type;
             withdraw.push(el);
           }
           else{
            delete el.block;
            delete el.symbol;
            delete el.from_type;
            delete el.to_type;
            deposit.push(el);
           }

         });
         res.json([{"WITHDRAWS": withdraw},{"DEPOSITS":deposit}]);
      }
    });
  }
  //ends else if
  else
  {
    const active_key = body.wif;
    const key = dsteem.PrivateKey.fromString(active_key);
    const account = "account";
    const my_id= "mainnet";
    const my_data= {"contractName":"tokens", "contractAction":"transfer","contractPayload":{"symbol": "omg",
    "to": body.to,"quantity":body.quantity,"memo": body.memo }};
    client.broadcast.json({
        required_auths: [account],
        required_posting_auths: [],
        id: my_id,
        json: JSON.stringify(my_data),
    }, key).then(
        result => {res.send(result)},
        error => {res.send({msg: 'Something went wrong', error: error})}
    )
  }
  //ends else
  });

app.listen(port, function () {
  console.log("Server listening on port: " + port);
});

【问题讨论】:

  • 你期望body(或者更确切地说req.body.curl)包含什么?
  • 好的,你不能在没有首先摆脱非 JSON 的情况下调用 JSON.parse()
  • @iBug 回滚。
  • @AlexMcMillan 谢谢。你知道评论是自动的吗? :P
  • @iBug 不,我没有 - 但该死的,这是选择!干得好:)

标签: javascript node.js rpc


【解决方案1】:

如果您的第一个 try/catch 块中出现错误,您的代码会中断,这是您身边的语义错误。

try
{
  var body=JSON.parse(req.body.curl);
}
catch(err)
{
   res.send({msg: 'invalid command', error: err});
}

1. JS中的变量提升

查看js中变量提升的话题:https://developer.mozilla.org/en-US/docs/Glossary/Hoisting

简而言之,根据您的示例,这意味着 JS 编译器将在函数的最顶部的 post 函数内创建一个名为 body 的变量,其初始值为 undefined。发生这种情况是因为您使用了 var 关键字,而不是 const/let。

只有在JSON.parse()正常工作的情况下,才会设置body变量的值。万一发生这种失败(这似乎发生在您身上)或出现错误,body 将永久保持未定义状态,这意味着您无法访问其属性,例如方法,因为它不是对象。

解决方案取决于您想在此处实现的目标:

  1. 您也可以将其余代码放入 try/catch 中
  2. 您还可以为 body 添加额外的检查
  3. 您可以稍微重构代码以提高可读性(当然,这总是主观的,取决于编码风格)

这里的重构示例:

app.post('/', function(req, res) {
  try {
    const body = JSON.parse(req.body.curl);

    switch (body.method) {
      case 'GET':
        this.handleGETRequest();
      case 'POST':
        this.handlePOSTRequest();
      default:
        this.handleDefault();
    }
  } catch (err) {
    res.send({ msg: 'invalid command', error: err });
  }
});

如果你想避免拆分成几个函数,你可以这样做

app.post('/', function(req, res) {
      try {
        const body = JSON.parse(req.body.curl);

        // Your current else 
        if(!body.method) {
            ...code
            return; // Will break the execution after this
        }

        ...your normal if/else here with simplified checks now
      } catch (err) {
        res.send({ msg: 'invalid command', error: err });
      }
    });

考虑到所有内容都包含在 try/catch 中,因此无需在此处专门检查 body 是否未定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2019-08-19
    相关资源
    最近更新 更多