这是一种脑力激荡问题,因为代码完全正常,它只会轻微刺激我的美感。我正在转向Stack Overflow,因为我自己的大脑现在正在让我失望。
以下是使用Google Maps JS API查找地址并在地图上放置标记的代码片段。但是,有时初始查找失败,所以我想用不同的地址重复该过程。
geocoder.getLatLng(item.mapstring, function(point) {
if (!point) {
geocoder.getLatLng(item.backup_mapstring, function(point) {
if (!point) return;
map.setCenter(point, 13);
map.setZoom(7);
map.addOverlay(new GMarker(point));
})
return;
}
map.setCenter(point, 13);
map.setZoom(7);
map.addOverlay(new GMarker(point));
})
(getLatLng
的第二个参数是回调函数。)
当然你可以看到中心和缩放地图并添加标记的三条线是重复的,一次在主要回调中,一次在“后备回调”中(哈哈)。你能找到一种方法来表达整个事物而没有任何冗余吗?如果您的解决方案适用于任意数量的备份地图字符串,您将获得奖励积分和我的奉承。
答案 0 :(得分:21)
其他答案都很好,但这里还有一个选择。这允许您保持与开始时相同的形式,但使用命名lambda函数的技巧,以便您可以递归地引用它:
mapstrings = ['mapstring1', 'mapstring2', 'mapstring3'];
geocoder.getLatLng(mapstrings.shift(), function lambda(point) {
if(point) {
// success
map.setCenter(point, 13);
map.setZoom(7);
map.addOverlay(new GMarker(point));
}
else if(mapstrings.length > 0) {
// Previous mapstring failed... try next mapstring
geocoder.getLatLng(mapstrings.shift(), lambda);
}
else {
// Take special action if no mapstring succeeds?
}
})
第一次使用符号“lambda”时,将它作为新的函数文字名称引入。第二次使用时,它是一个递归引用。
函数文字命名在Chrome中有效,我认为它可以在大多数现代浏览器中使用,但我没有测试它,我也不知道旧浏览器。
答案 1 :(得分:8)
有一种非常好的方法可以在不明确支持递归的语言结构中执行递归,称为定点组合器。最着名的是Y-Combinator。
Here is the Y combinator for a function of one parameter in Javascript:
function Y(le, a) {
return function (f) {
return f(f);
}(function (f) {
return le(function (x) {
return f(f)(x);
}, a);
});
}
这看起来有点吓人,但你只需写一次。使用它实际上非常简单。基本上,你将一个参数的原始lambda,并将其转换为两个参数的新函数 - 第一个参数现在是可以执行递归调用的实际lambda表达式,第二个参数是原始的第一个参数( point
)您想要使用。
这是您在示例中使用它的方法。请注意,我使用mapstrings
作为要查找的字符串列表,pop函数会破坏性地从头部删除元素。
geocoder.getLatLng(pop(mapstrings), Y(
function(getLatLongCallback, point)
{
if (!point)
{
if (length(mapstrings) > 0)
geocoder.getLatLng(pop(mapstrings), getLatLongCallback);
return;
}
map.setCenter(point, 13);
map.setZoom(7);
map.addOverlay(new GMarker(point));
});
答案 2 :(得分:2)
是的,将其分解为函数:)
geocoder.getLatLng(item.mapstring, function(point) {
if (!point) {
geocoder.getLatLng(item.backup_mapstring, function(point) {
if (point) {
setPoint(point);
}
})
return;
}
function setPoint(point) {
map.setCenter(point, 13);
map.setZoom(7);
map.addOverlay(new GMarker(point));
}
setPoint(point);
});
答案 3 :(得分:1)
这个怎么样?
function place_point(mapstrings,idx)
{
if(idx>=mapstrings.length) return;
geocoder.getLatLng(mapstrings[idx],
function(point)
{
if(!point)
{
place_point(mapstrings,idx+1);
return;
}
map.setCenter(point, 13);
map.setZoom(7);
map.addOverlay(new GMarker(point));
});
}
尽可能多的备份字符串。只需在第一次使用0作为第二个参数时调用它。