Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在NodeJs中使用请求进行多个API调用?_Javascript_Node.js_Ecmascript 6_Request_Ejs - Fatal编程技术网

Javascript 如何在NodeJs中使用请求进行多个API调用?

Javascript 如何在NodeJs中使用请求进行多个API调用?,javascript,node.js,ecmascript-6,request,ejs,Javascript,Node.js,Ecmascript 6,Request,Ejs,创建一个简单的Node.Js应用程序,其中需要显示来自两个API的数据,其中两个API都返回多个ID为的对象 需要在单个页面上显示来自这两个API的数据,并且需要基于ID从这两个API获取数据 API 1响应如下所示: { "hikes": [ { "id": 1, "active": true, "name": "Mt. Everest", },

创建一个简单的
Node.Js
应用程序,其中需要显示来自两个API的数据,其中两个API都返回多个ID为的对象

需要在单个页面上显示来自这两个API的数据,并且需要基于ID从这两个API获取数据

API 1响应如下所示:

    {
    "hikes": [
        {
            "id": 1,
            "active": true,
            "name": "Mt. Everest",          
        },
        {
            "id": 2,
            "active": true,
            "name": "K2",          
        },
        {
            "id": 3,
            "active": true,
            "name": "Mt. Kinley",          
        },
    ]
}
{
    "hikes": [
        {
            "id": 1,
            "slots": 50,
            "available": 23,          
        },
        {
            "id": 2,
            "slots": 20,
            "available": 1,          
        },
        {
            "id": 3,
            "slots": 43,
            "available": 20,          
        },
    ]
}
var port    = process.env.PORT || 3000,
    express = require("express"),
    request = require("request"),
    app = express();

app.set("view engine", "ejs");





var hikes = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
  };

  var availability = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
  };


app.get("/", function(req, res){


      function callback(error, response, body){
          if(!error && response.statusCode == 200){
              var data = JSON.parse(body);
              res.render("index", {data: data});
              })
          }
      }
    request(hikes, callback);
});


app.listen(port, function(){
    console.log("Running");
});
API 2响应如下所示:

    {
    "hikes": [
        {
            "id": 1,
            "active": true,
            "name": "Mt. Everest",          
        },
        {
            "id": 2,
            "active": true,
            "name": "K2",          
        },
        {
            "id": 3,
            "active": true,
            "name": "Mt. Kinley",          
        },
    ]
}
{
    "hikes": [
        {
            "id": 1,
            "slots": 50,
            "available": 23,          
        },
        {
            "id": 2,
            "slots": 20,
            "available": 1,          
        },
        {
            "id": 3,
            "slots": 43,
            "available": 20,          
        },
    ]
}
var port    = process.env.PORT || 3000,
    express = require("express"),
    request = require("request"),
    app = express();

app.set("view engine", "ejs");





var hikes = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
  };

  var availability = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
  };


app.get("/", function(req, res){


      function callback(error, response, body){
          if(!error && response.statusCode == 200){
              var data = JSON.parse(body);
              res.render("index", {data: data});
              })
          }
      }
    request(hikes, callback);
});


app.listen(port, function(){
    console.log("Running");
});
需要拉取这两个API,获取数据并在页面上呈现以显示“名称”、“插槽”和“可用”

到目前为止,我成功地拉取了其中一个API,并将数据传递到呈现的
index.ejs
页面,但我不确定应该如何拉取第二个API,以及如何获取数据

目前我的代码如下所示:

    {
    "hikes": [
        {
            "id": 1,
            "active": true,
            "name": "Mt. Everest",          
        },
        {
            "id": 2,
            "active": true,
            "name": "K2",          
        },
        {
            "id": 3,
            "active": true,
            "name": "Mt. Kinley",          
        },
    ]
}
{
    "hikes": [
        {
            "id": 1,
            "slots": 50,
            "available": 23,          
        },
        {
            "id": 2,
            "slots": 20,
            "available": 1,          
        },
        {
            "id": 3,
            "slots": 43,
            "available": 20,          
        },
    ]
}
var port    = process.env.PORT || 3000,
    express = require("express"),
    request = require("request"),
    app = express();

app.set("view engine", "ejs");





var hikes = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
  };

  var availability = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
  };


app.get("/", function(req, res){


      function callback(error, response, body){
          if(!error && response.statusCode == 200){
              var data = JSON.parse(body);
              res.render("index", {data: data});
              })
          }
      }
    request(hikes, callback);
});


app.listen(port, function(){
    console.log("Running");
});
在我的index.ejs中,我现在创建了一个简单的循环来打印名称:

<% data["hikes"].forEach(function(hike){ %>

    <p><%= hike.name %></p>

<% }) %>

有没有办法解决这个问题


谢谢

创建页面有两种可能的选项:

  • 缓存来自两个API的应答
  • 对他们的代理请求
你需要选择你将使用什么

对于缓存使用
setInterval
将答案存储到两个变量对象中,每5/60/N秒一个


对于代理使用异步/等待方法和
承诺。所有
在得到两个答案后继续工作。在这种情况下,我建议将
请求
包更改为

,我希望您阅读更多有关承诺和异步函数的内容,以便更好地理解和解决问题

目前,这将对您有效:

var hikes = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
};

var availability = {
    url: "https://api.com/hikes",
    headers: {
      'Identifier': identifier
    }
};


app.get("/", function(req, res){


    function callback(error, response, body){
        if(!error && response.statusCode == 200){

            var data = JSON.parse(body);

            request(availability, (err, response, body) => {

                if(!err && response.statusCode == 200){

                    var data2 = JSON.parse(body);

                    res.render("index", {data1: data, data2: data2});

                }

            });

        }
    }
    request(hikes, callback);
});
index.ejs

<% data1["hikes"].forEach(function(hike){ %>

    <p><%= hike.name %></p>

<% }) %>

<% data2["availability"].forEach(function(available){ %>

    <p><%= available.slots %></p>
    <p><%= available.available %></p>

<% }) %>
更好的
索引.ejs

<% if (hikes.length>0) { %>
    <% if (availability.length>0) { %>
        <% for (var i = 0; i < hikes.length; i++) { %>

            <p><%= hikes[i].name %></p>
            <p><%= availability[i].slots %></p>
            <p><%= availability[i].available %></p>

        <% } %>
    <% } %>
<% } %>
0){%>
0) { %>


如果我理解正确,我假设您正在尝试从两个API获取数据,并希望根据对象id将数据合并到单个对象数组中并将其传递给视图。如果是这种情况,则可以使用从两个API并行获取数据,然后将数据合并到一个对象数组中并将其传递给视图ode将帮助您理解实现

var port    = process.env.PORT || 3000,
express = require("express"),
request = require("request"),
app = express();

var async = require('async');


app.set("view engine", "ejs");


var hikes = {
  url: "https://api.com/hikes",
  headers: {
   'Identifier': identifier
  }
};

var availability = {
  url: "https://api.com/hikes",
  headers: {
    'Identifier': identifier
  }
};


app.get("/", function(req, res) {
  function callback(error, response, body, cb) {
    if(error || response.statusCode != 200)
      return cb(true);

    cb(null, JSON.parse(body).hikes);//instead of sending data directly to view, send it to async callback to merge it latter
  }

  var tasks = { // tasks to run in parallel
    hikes: function (cb) {
      request(hikes, function (error, response, body) {
        callback(error, response, body, cb);
      });
    },
    availability: function (cb) {
      request(availability, function (error, response, body) {
        callback(error, response, body, cb);
      });
    }
  };

  async.parallel(tasks, function (err, resp) {
    if(err) {
      //handle error here, the error could be caused by any of the tasks.
      return;
    }

    var availabilityIdMap = resp.availability.map(function (availability) { return availability.id; });//get an array of all the availability ids
    var data = resp.hikes.map(function (hike) { //merging hike to corresponding availability object
      var availabilityIndex = availabilityIdMap.indexOf(hike.id); // finding the availability against the hike id.
      if(availabilityIndex < 0) //availability not found, just return hike
        return hike;

      var matchingAvailabilityObj = resp.availability[availabilityIndex]; //get the matching availability object
      var mergedObj = Object.assign(hike, matchingAvailabilityObj); //merge both objects
      return mergedObj;
    });

    // now the data will have an array of merged object with properties from hike and availability objects
    res.render("index", {data: data});
  });
});


app.listen(port, function(){
  console.log("Running");
});
var-port=process.env.port | 3000,
快递=要求(“快递”),
请求=要求(“请求”),
app=express();
var async=require('async');
应用程序集(“查看引擎”、“ejs”);
风险值上升={
url:“https://api.com/hikes",
标题:{
“标识符”:标识符
}
};
var可用性={
url:“https://api.com/hikes",
标题:{
“标识符”:标识符
}
};
应用程序获取(“/”,函数(请求,恢复){
函数回调(错误、响应、正文、cb){
if(错误| | response.statusCode!=200)
返回cb(true);
cb(null,JSON.parse(body.hikes);//不直接将数据发送到视图,而是将其发送到异步回调以合并到后者
}
var tasks={//要并行运行的任务
hikes:功能(cb){
请求(hikes、功能(错误、响应、正文){
回调(错误、响应、正文、cb);
});
},
可用性:功能(cb){
请求(可用性、功能(错误、响应、正文){
回调(错误、响应、正文、cb);
});
}
};
async.parallel(任务、函数(err、resp){
如果(错误){
//处理错误在这里,错误可能是由任何任务引起的。
返回;
}
var availabilityIdMap=resp.availability.map(函数(可用性){return availability.id;});//获取所有可用性id的数组
var data=resp.hikes.map(函数(hike){//将hike合并到相应的可用性对象
var availabilityIndex=availabilityiddmap.indexOf(hike.id);//根据hike id查找可用性。
如果(availabilityIndex<0)//找不到可用性,只需返回
返程远足;
var matchingAvailabilityObj=resp.availability[availabilityIndex];//获取匹配的可用性对象
var mergedObj=Object.assign(hike,matchingAvailabilityObj);//合并两个对象
返回Dobj;
});
//现在,数据将有一个合并对象数组,其中包含hike和availability对象的属性
res.render(“索引”{data:data});
});
});
app.listen(端口,函数(){
控制台日志(“运行”);
});

通过多个请求函数解决了概念。结果,全局变量可以访问多个所需的api值。节点v10.15.1:

// require node packages
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
//set app to use express package
const app = express();
//let app use body-parser package
app.use(bodyParser.urlencoded({extended:true}));
// let app set ejs as the view engine
app.set("view engine", "ejs");
// set view path
const view = __dirname + "/app/views/";
解决方案从这里开始:

//assign api to constant
const btcUsd = "https://apiv2.bitcoinaverage.com/indices/global/ticker/BTCUSD";
const trxBtc = "https://apiv2.bitcoinaverage.com/indices/tokens/ticker/TRXBTC";

// function containing api parser
function tickers(){
 request(btcUsd, function(error, response, body){
    // handle errors if any
    if(error){
      console.log(error);
    } else {
      // parse json
      let data = JSON.parse(body);
      // get last price
      btc = (data.last).toFixed(2);
      console.log(btc);
    }
  });

  request(trxBtc, function(error, response, body){
    // handle errors if any
    if(error){
      console.log(error);
    } else {
      // parse json
      let data = JSON.parse(body);
      // get last price
      usdConvert = (data.last) * btc;
      trx = usdConvert.toFixed(4);
      console.log(trx);
    }
  });
}
// function to trigger ticker function and set interval. (this is optional)
function getTickers(){
  tickers();
  // set interval
  setInterval(tickers, 60000);
}

//activate getTickers function
getTickers();
现在,将每个值指定给对象键的任何渲染视图都可以使用所需的api值btc和trx:

// render view
app.get("/", function(req, res){
 res.render(views + "pages/index", {btcTicker: btc, trxTicker: trx});
});
鉴于:

<h1> <%= btcTicker %> </h1>
<br>
<h1> <%= trxTicker %> </h1>



非常感谢,我将对此进行测试!在使用承诺时,我是否应该使用“请求承诺”npm包?我尝试使用带有“请求承诺”的代码,但收到一条错误消息说“ReferenceError:错误未定义”不,它的javascript新功能在V6T以上的任何版本中都可用。这看起来非常接近。我得到一个错误“resp.availability.map不是一个函数。我还看到我在最初的帖子中写了一个拼写错误,API首先返回“hikes”,而不是“hike”和“availability”-这可能与问题有关吗?不,这不是问题所在。实际上,您的API正在返回一个包含属性hikes的JSON对象。我假设API响应将是一个数组,这就是出现错误的原因。现在,我已经更改了API的回调函数。函数回调(error,response,body,cb){if(错误| | response.statusCode!=200)返回cb(true);cb(null,JSON.parse(body.hikes);//现在我只从对象返回hikes数组,而不是返回整个对象。}它对您有效吗?如果有效,请将其标记为应答。