如何从api调用中获取值并将其存储在变量中并更新dynamodb记录

时间:2019-01-21 21:34:28

标签: node.js aws-lambda amazon-dynamodb aws-sdk unirest

我有一个Web请求,该请求获取一些数据并返回响应。我正在寻找如何将响应存储在变量中,以便稍后在代码中使用它。

这是针对在lambda函数中运行的节点js

/ **  *主要执行与车辆接口操作的操作  * Amazon DynamoDB表。  *  * @级车  * /

/**
 * Registers a vehicle to and owner.
 * @param {JSON} ticket - authentication ticket
 * @param {JSON} vehicle - vehicle object
 * @param {createVehicle~callback} cb - The callback that handles the response.
 */
vehicle.prototype.createVehicle = function(ticket, vehicle, cb) {
    let vehicle_data = [];
    vehicle_data.push(vehicle);
    let vin_data = _.pluck(vehicle_data, 'vin');
    let vin_number = vin_data[0];
    console.log(vin_number);

    var options = {
        url: 'https://vindecoder.p.mashape.com/decode_vin?' + 'vin=' + vin_number,
        headers: {"X-Mashape-Key": "XXXXXXXXXXXXXXXXXXXXXXXXXX","Accept": "application/json"}
      };

      var data;

      function callback(error, response, body) {
        if (!error && response.statusCode == 200) {
          var result = JSON.parse(body);
          var data = result['specification'];
          //console.log(data);
        }
      }
    request(options, callback);

    var year = data['year'];
    var make = data['make'];
    var model = data['model'];
    var trim_level = data['trim_level'];
    var engine = data['engine'];
    var body_style = data['style'];
    var made_in = data['made_in'];
    var steering_type = data['steering_type'];
    var anti_brake_system = data['anti_brake_system'];
    var fuel_tank = data['tank_size'];
    var overall_height = data['overall_height'];
    var overall_length = data['overall_length'];
    var overall_width = data['overall_width'];
    var standard_seating = data['standard_seating'];
    var optional_seating = data['optional_seating'];
    var highway_mileage = data['highway_mileage'];
    var city_mileage = data['city_mileage'];

    vehicle.owner_id = ticket['cognito:username'];
    // vehicle.vehicle_year = year;
    // vehicle.make = make;
    // vehicle.model = model;
    // vehicle.trim_level = trim_level;
    // vehicle.engine = engine;
    // vehicle.body_style = style;
    // vehicle.made_in = made_in;
    // vehicle.steering_type = steering_type;
    // vehicle.anti_brake_system = anti_brake_system;
    // vehicle.fuel_tank = fuel_tank;
    // vehicle.overall_height = overall_height;
    // vehicle.overall_length = overall_length;
    // vehicle.overall_width = overall_width;
    // vehicle.standard_seating = standard_seating;
    // vehicle.optional_seating = optional_seating;
    // vehicle.highway_mileage = highway_mileage;
    // vehicle.city_mileage = city_mileage;

    let params = {
        TableName: ddbTable,
        Item: vehicle
    };

    let docClient = new AWS.DynamoDB.DocumentClient(dynamoConfig);
    docClient.put(params, function(err, data) {
        if (err) {
            console.log(err);
            return cb(err, null);
        }

        return cb(null, vehicle);
    });

};

我希望api调用的响应存储在一个对象中,以便可以用来更新dynamodb记录

1 个答案:

答案 0 :(得分:0)

您的代码中存在各种问题。请参阅我在代码中留下的注释。 您的函数由于javascript的异步特性而失败。基本上,您有一个请求回调,其结果在其余代码中都看不到。使用promise和async / await是解决此问题的一种干净方法。见下文:

    // use request promise instead of request
    // promises will make your life much easier
    // https://hackernoon.com/javascript-promises-and-why-async-await-wins-the-battle-4fc9d15d509f
    // https://github.com/request/request-promise
    const request = require('request-promise')

    vehicle.prototype.createVehicle = function(ticket, vehicle, cb) {
        // No need to use var anymore with es6, just use let and const
        // https://www.sitepoint.com/es6-let-const/

        let vehicle_data = [];
        vehicle_data.push(vehicle);
        let vin_data = _.pluck(vehicle_data, "vin");
        let vin_number = vin_data[0];
        console.log(vin_number);

        const options = {
            uri: "https://vindecoder.p.mashape.com/decode_vin?" + "vin=" + vin_number,
            headers: {
                "X-Mashape-Key": "XXXXXXXXXXXXXXXXXXXXXXXXXX",
                Accept: "application/json"
            }
        };


      // Here's the main mistake
      // request has a callback function that is asynchronous
      // the rest of your code never sees the result because the result doesn't leave the callback
      // your code continues to execute without waiting for the result (this is the gist of asynchronity in js)

      // function callback(error, response, body) {
      //   if (!error && response.statusCode == 200) {
      //     const result = JSON.parse(body);
      //     const data = result["specification"]; // this variable doesn't leave the scope of this callback
      //     //console.log(data);
      //   }
      // }

      // therefore this is the failure point
      // request(options, callback);

      // Do this instead
      // here I utilize promises and async/ await
      // https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee
      try {
        const result = await request(options);
        const data = result["specification"];

      } catch (error) {
        console.log(error);
      }

      // Now data is available to be used below in dynamodb

      // also, utilize objects, its much cleaner
      const carVariables = {
          year: data["year"],
          make: data["make"],
          model: data["model"],
          trim_level: data["trim_level"],
          engine: data["engine"],
          body_style: data["style"],
          made_in: data["made_in"],
          steering_type: data["steering_type"],
          anti_brake_system: data["anti_brake_system"],
          fuel_tank: data["tank_size"],
          overall_height: data["overall_height"],
          overall_length: data["overall_length"],
          overall_width: data["overall_width"],
          standard_seating: data["standard_seating"],
          optional_seating: data["optional_seating"],
          highway_mileage: data["highway_mileage"],
          city_mileage: data["city_mileage"],
      };


        vehicle.owner_id = ticket["cognito:username"];
        vehicle = { ...vehicle, ...carVariables} // ES6 spread operator does the below code for you:
        // one line versus 20. win. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

        // vehicle.vehicle_year = year;
        // vehicle.make = make;
        // vehicle.model = model;
        // vehicle.trim_level = trim_level;
        // vehicle.engine = engine;
        // vehicle.body_style = style;
        // vehicle.made_in = made_in;
        // vehicle.steering_type = steering_type;
        // vehicle.anti_brake_system = anti_brake_system;
        // vehicle.fuel_tank = fuel_tank;
        // vehicle.overall_height = overall_height;
        // vehicle.overall_length = overall_length;
        // vehicle.overall_width = overall_width;
        // vehicle.standard_seating = standard_seating;
        // vehicle.optional_seating = optional_seating;
        // vehicle.highway_mileage = highway_mileage;
        // vehicle.city_mileage = city_mileage;

        let params = {
            TableName: ddbTable,
            Item: vehicle
        };

        // This will now probably work. yay!

        let docClient = new AWS.DynamoDB.DocumentClient(dynamoConfig);
        docClient.put(params, function(err, data) {
            if (err) {
                console.log(err);
                return cb(err, null);
            }

            return cb(null, vehicle);
        });
    };

这未经测试,但我认为应该可以。可能会有一些错别字或其他任何东西,但主要的收获是使用promise和async / await等待并暴露请求的结果。请参阅评论中的链接和参考,以进一步阅读。