【问题标题】:Array empty after pushes were made in get request in Node.js/Express在 Node.js/Express 中的 get 请求中进行推送后数组为空
【发布时间】:2018-04-23 21:12:29
【问题描述】:

我正在编写一个调用 API 来获取 URL 的函数。这些是我希望完成的步骤:

  1. 将对象(餐厅)数组作为参数解析
  2. 对于每个对象,调用 Google 搜索 API 以获取一些图片网址
  3. 将这些 imageURL 存储在一个数组中
  4. 将 imageURLs 作为名为 imageURLs 的属性添加到参数中数组中的每个对象

代码能够在 GET 请求中记录 imageURLs,但在请求之外,imageURLs 只是一个空数组。

var googleSearch = function(restaurants, cb){   
        console.log("google starts");   
        const apiKey = google_apiKey;   
        const cseKey = cseID;

         Array.from(restaurants).forEach(function(restaurant){   

    var keyWord = restaurant.name + " "+ restaurant.location.city
      + " "+ restaurant.location.state + " food";

    var googleURL = "https://www.googleapis.com/customsearch/v1?key="+ apiKey +
      "&q="+ keyWord +
      "&searchType=image" +
      "&cx=" + cseKey +
      "&num=7" +
      "&safe=medium"
    ;

    //image URLs of each restaurants to be displayed in the front end   
  var imageURLs = [];

  request
      .get(googleURL,
        {
          json : true, headers: {
            'User-Agent' : 'thaorell'
          }
        })
      .then(function(response){
          Array.from(response.items).forEach(function(item){
            imageURLs.push(item.link)
          });
        })
      .catch(e => {
        console.log(e);
      })
      restaurant.imageURLs = imageURLs
   })   
 cb(null, restaurants);
}

【问题讨论】:

  • 您正在使用异步 API 并在完成请求之前调用 cb。你应该把你的 cb 调用放到你最后一个 .then 链中。
  • cb不应该在请求之后吗?为什么在请求完成之前调用它?
  • 异步意味着“不考虑时间”,这意味着时间与函数的其余部分何时运行无关

标签: javascript node.js rest express asynchronous


【解决方案1】:

你误解了 Promise API:

var googleSearch = function (restaurants, cb) {
  console.log("google starts");
  const apiKey = google_apiKey;
  const cseKey = cseID;

  return Promise.all(Array.from(restaurants).map(function (restaurant) {

    var keyWord = restaurant.name + " " + restaurant.location.city
      + " " + restaurant.location.state + " food";

    var googleURL = "https://www.googleapis.com/customsearch/v1?key=" + apiKey +
      "&q=" + keyWord +
      "&searchType=image" +
      "&cx=" + cseKey +
      "&num=7" +
      "&safe=medium"
      ;

    return request
      .get(googleURL,
        {
          json: true, headers: {
            'User-Agent': 'thaorell'
          }
        }
      )
      .then(function (response) {
        restaurant.imageURLs = Array.from(response.items).map(function (item) {
          return item.link;
        });
        return restaurant;
      })
    })
  )
    .then(restaurants2 => cb(null, restaurants2))
    .catch(cb)
}

如您所见,在将数据传回回调之前,您需要等待所有请求完成。

【讨论】:

  • 它返回了一个空对象。还有其他方法可以等待所有请求执行吗?
  • 哎呀!我确实做了坏事。我在修复它时误读了一行。给我一点时间。好的,我将 forEach(no return) 更改为 map(创建一个数组),现在应该使它成为这样,以便餐厅应该有一个数组
  • 更新了另一个缺少的回报。 @CharlesThao 我可以要求您进一步澄清一下您对空对象的含义吗?
  • 最后的 cb,又名 restaurant2 返回 {}
  • 如果没有看到更多代码,我将无法尝试提供更多帮助。我所做的只是更正您的数据返回的承诺顺序,以确保当它调用回调时,它将等待所有数据加载,将图像 URL 关联到餐厅,并返回餐厅列表
猜你喜欢
  • 2012-03-23
  • 1970-01-01
  • 2016-05-06
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多