Javascript回调内部地图

时间:2015-08-19 04:15:22

标签: javascript node.js google-maps asynchronous

当我尝试从map函数的回调中返回时,我正遇到问题。与异步代码的情况一样,map函数在异步调用完成之前完成,这意味着我丢失了数据。

我可以在map函数中做些什么来确保异步调用完成?我试图只从一个promise返回,但似乎map函数在到达结尾时返回null。

在我的具体示例中,我尝试从Yelp API中获取大量业务,然后对其各自的地址进行地理编码,以便将其添加到我网站上的Google地图中。

代码:

Q.Promise(function(resolve, reject, notify) {
  yelp.search({
    category_filter: 'food,restaurants',
    location: city, 
    limit: 3, 
    sort: 2, // sort mode: 2=Highest Rated
  }, function(error, data) {
    if (error) {
      reject(new Error(error));
    }
    else {
      if (data['businesses'] && data['businesses'].length > 0) {
        results = data['businesses'].map(function(business) {
          sleep.usleep(500000); // sleep for 0.5 seconds so as not to get throttled by google
          address = business.location.display_address.join(', ');
          geocoder.geocode(address)
            .then(function(res) {
              return {
                img_url: business.image_url,
                name: business.name,
                url: business.url,
                rating_img_url: business.rating_img_url,
                address: address,
                coords: [res[0]['latitude'], res[0]['longitude']],
              }
            })
            .catch(function(err) {
              console.log('Could not geocode: ' + err);
              return;
            });
        });
        resolve(results);
      }
    }
  });
});

2 个答案:

答案 0 :(得分:0)

我讨厌提出一种不那么“功能性”的方法(see wikipedia,特别是关于副作用的部分),但是如果你愿意使用一个改变对象属性的简单循环,那么应该这样做:< / p>

data.forEach(function(business) {
          // code removed
            .then(function(res) {
              business.businesses = /* the new object */
            })
            // code removed

在上述方法中,您只需迭代data并改变当前迭代businesses的相应business属性。

我认为大多数其他方法可能有点复杂/混淆,所以这可能是“较少的邪恶”类型的东西。其他选项包括将所有承诺存储在新阵列中,并使用Q.allSettled之类的东西将它们与相应的business属性相匹配。但不确定这是否是一种最佳方法。

答案 1 :(得分:0)

除了Josh Beam的回答之外,我将发布一个我想到的解决方案,它实际上将地理编码代码放入一系列被调用的Promise中,然后返回Yelp承诺的结果。 :

Q.Promise(function(resolve, reject, notify) {
  yelp.search({
    category_filter: 'food,restaurants',
    location: city, 
    limit: 3, 
    sort: 2, // sort mode: 2=Highest Rated
  }, function(error, data) {
    if (error) {
      reject(new Error(error));
    }
    else {
      if (data['businesses'] && data['businesses'].length > 0) {
        // we only need some of the properties of a Yelp business result
        geoQueries = [];
        results = data['businesses'].map(function(business) {
          geoQueries.push(Q.Promise(function(resolve, reject, notify) {
            // sleep for 0.5 seconds so as not to get throttled by google
            sleep.usleep(500000); 

            address = business.location.display_address.join(', ');
            geocoder.geocode(address)
            .then(function(res) {
              resolve({
                img_url: business.image_url,
                name: business.name,
                url: business.url,
                rating_img_url: business.rating_img_url,
                address: address,
                coords: [res[0]['latitude'], res[0]['longitude']],
              });
            })
            .catch(function(err) {
              console.log('Could not geocode: ' + err);
              return;
            });
          }));
        });

        Q.all(geoQueries)
        .then(function(data) {
          resolve(data);
        });
      }
    }
  });
});