映射内的Javascript回调
当我试图从映射内的Javascript回调,javascript,node.js,google-maps,asynchronous,Javascript,Node.js,Google Maps,Asynchronous,当我试图从map函数中的回调返回时,当前遇到了一个问题。与异步代码通常的情况一样,map函数在异步调用完成之前完成,这意味着我丢失了数据 在map函数中我可以做什么来确保异步调用完成?我试图只从承诺中返回,但似乎map函数在到达末尾时返回null 在我的具体例子中,我试图从YelpAPI中获取一些企业,然后对它们的地址进行地理编码,这样我就可以将它们添加到我网站上的谷歌地图中 代码: 我不喜欢建议一种不太“实用”的方法(特别是关于副作用的部分),但是如果你愿意使用一个简单的循环来改变对象属性,它
map
函数中的回调返回时,当前遇到了一个问题。与异步代码通常的情况一样,map函数在异步调用完成之前完成,这意味着我丢失了数据
在map
函数中我可以做什么来确保异步调用完成?我试图只从承诺中返回,但似乎map函数在到达末尾时返回null
在我的具体例子中,我试图从YelpAPI中获取一些企业,然后对它们的地址进行地理编码,这样我就可以将它们添加到我网站上的谷歌地图中
代码:
我不喜欢建议一种不太“实用”的方法(特别是关于副作用的部分),但是如果你愿意使用一个简单的循环来改变对象属性,它应该做到:
data.forEach(function(business) {
// code removed
.then(function(res) {
business.businesses = /* the new object */
})
// code removed
在上述方法中,您只需迭代数据
,并修改当前迭代的业务
的相应业务
属性
我认为大多数其他方法可能有点复杂/模糊,因此这可能是一种“较小的邪恶”类型的事情。其他选项包括将所有承诺存储在一个新数组中,并使用类似于Q.allSettled
的内容将它们与相应的业务
属性相匹配。不过,我不确定这是否是一种最佳方法。我讨厌建议一种“功能性”较差的方法(尤其是关于副作用的部分),但如果您愿意使用一个简单的循环来改变对象属性,它应该做到:
data.forEach(function(business) {
// code removed
.then(function(res) {
business.businesses = /* the new object */
})
// code removed
在上述方法中,您只需迭代数据
,并修改当前迭代的业务
的相应业务
属性
我认为大多数其他方法可能有点复杂/模糊,因此这可能是一种“较小的邪恶”类型的事情。其他选项包括将所有承诺存储在一个新数组中,并使用类似于
Q.allSettled
的内容将它们与相应的业务
属性相匹配。不过,我不确定这是否是一种最佳方法。除了Josh Beam的答案之外,我还将发布一个我想到的解决方案,在返回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);
});
}
}
});
});
除了Josh Beam的回答之外,我还将发布一个我想到的解决方案,在返回Yelp promise的结果之前,它实际上将地理编码代码放入一系列单独的承诺中,并被调用
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);
});
}
}
});
});
我目前正在考虑在一个承诺中做一个承诺(因此我将做Q.all(地理查询))。你认为这个解决方案比你的有什么优点?还有,为什么forEach不能像map那样在异步回调中失败呢?@tsurantino,我尽量避免使用承诺中的承诺方法,因为它通常会非常不可读。我认为
forEach
不会“失败”,因为then
内部的回调只是存储对当前迭代的业务的引用,当承诺解决时,它调用适当的回调并映射到适当的对象。我可能错了,但在我们现在正在进行的项目中,这种模式或多或少地被“成功”使用了。这是有道理的!我现在正忙着,所以我将把承诺中的承诺作为另一个可选答案发布。我回家后要试试你的方法。如果它有效并且可读性更好,我将奖励你的答案:)再次感谢你花时间回复。@tsurantino,当然没问题!希望你能找到一个合适的解决方案。我目前正在考虑在一个承诺中做一个承诺(所以我会做Q.all(geoQueries))。你认为这个解决方案比你的有什么优点?还有,为什么forEach不能像map那样在异步回调中失败呢?@tsurantino,我尽量避免使用承诺中的承诺方法,因为它通常会非常不可读。我认为forEach
不会“失败”,因为then
内部的回调只是存储对当前迭代的业务的引用,当承诺解决时,它调用适当的回调并映射到适当的对象。我可能错了,但在我们现在正在进行的项目中,这种模式或多或少地被“成功”使用了。这是有道理的!我现在正忙着,所以我将把承诺中的承诺作为另一个可选答案发布。我回家后要试试你的方法。如果它有效并且可读性更好,我将奖励你的答案:)再次感谢你花时间回复。@tsurantino,当然没问题!希望你能找到一个合适的解决方案。