我有一个奇怪的问题,就是我在过去的几个小时里一直在撞墙。
我正在使用Appcelerator Titanium中的iPhone应用程序,它目前想要等到其他代码运行才能获得几个HTTPClient请求的结果,尽管事实上我在尝试之前正在调用它们使用他们的结果。
function getMarkers(e, miles){ //The function with the HTTPClient calls that are firing last, trimmed to have only the relevant code.
var markers = [];
Ti.API.info("Getting markers");
xhr.onload = function()
{
var data = Ti.XML.parseString(this.responseText);
var ref = data.documentElement.getElementsByTagName("reference");
for(var i =0; i < ref.length; i++){
var marker = new Object();
marker.ref = ref.item(i).text;
var request = Titanium.Network.createHTTPClient();
request.setTimeout(10000);
request.onload = function(){
var data = Ti.XML.parseString(this.responseText);
marker.address = data.documentElement.getElementsByTagName("formatted_address").item(0).text;
if(data.documentElement.getElementsByTagName("formatted_phone_number") != null){
marker.phone = data.documentElement.getElementsByTagName("formatted_phone_number").item(0).text;
} else {
marker.phone = null;
}
marker.icon = data.documentElement.getElementsByTagName("icon").item(0).text;
marker.lat = data.documentElement.getElementsByTagName("lat").item(0).text;
marker.lng = data.documentElement.getElementsByTagName("lng").item(0).text;
marker.name = data.documentElement.getElementsByTagName("name").item(0).text;
if(data.documentElement.getElementsByTagName("url") != null) {
marker.url = data.documentElement.getElementsByTagName("url").item(0).text;
} else {
marker.url = null;
}
markers.push(marker);
Ti.API.info(markers.length);
}
request.open("GET","https://maps.googleapis.com/maps/api/place/details/xml?reference=" + marker.ref + "&sensor=true&key=" + Ti.App.apiKey);
request.send();
}
};
xhr.open("GET","https://maps.googleapis.com/maps/api/place/search/xml?location=" + googleLatLng + "&radius=" + radius + "&types=" + Ti.App.types + "&sensor=true&key=" + Ti.App.apiKey);
xhr.send();
return markers;
}
// actually draw the markers on the map
function drawMap(markers, currentLoc)
{
var i;
Ti.API.info("Adding markers...");
for(i=0;i<markers.length;i++)
{
Ti.API.info("Marker " + i);
Ti.API.info(markers[i].name);
var ann = Titanium.Map.createAnnotation({
image:markers[i].icon,
animate:true,
latitude:markers[i].lat,
longitude:markers[i].lng,
title:markers[i].name,
subtitle:markers[i].address
});
if(markers[i].url != null){
ann.rightButton = markers[i].url;
}
mapview.addAnnotation(ann);
}
Ti.API.info("Markers added"); //When this block is called, markers.length == 0
}
// find the user's location and mark it on the map
function waitForLocation(e)
{
//Do stuff about finding current location and marking it on the map. This stuff works and a pin drops for the current location
drawMap(getMarkers(e), currentLoc);
}
首先调用waitForLocation,然后调用其他的。 Xcode输出以下内容:
[INFO] Getting markers
[INFO] Adding markers...
[INFO] Markers added
[INFO] 1
[INFO] 2
[INFO] 3
[INFO] 4
这意味着它将进入getMarkers函数(第一行),然后离开它(接下来的两行),然后返回到getMarkers函数以实际获取标记(最后四行,markers.length
的输出随着每个标记的添加)。知道了
我根据我在此处找到的答案移动了.open()
来电之前的.onload()
来电,但无论.open()
是.onload()
之前还是之后,我都会这样做。< / p>
我发现httpClient调用异步执行其任务的信息(API参考中缺少的一小部分信息)。知道这一点,它离开功能是有道理的,但它确实搞砸了信息的处理方式,因为我需要在尝试添加它们之前下载标记。
在与我的iPhone开发人员同事交谈时,他提到他使用委托和delegate.connectionDidFinishLoading调用来处理它们。或许,是否有一种方法可以使用它,或者我可以使用的Titanium实现?
还有另一种好方法可以确保它在应用程序实际下载之前不会尝试加载标记吗?它只需要适用于iPhone,因此特定于iPhone的选项都可以。
答案 0 :(得分:1)
经过大量的搜索和拔毛后,我终于设法让它按照我需要的方式工作。
.open()
有一个第三个布尔值参数,它强制HTTPClient同步运行(文档中未提及的另一个花絮)。将其设置为false
将使其同步运行。这样做允许我按照我期望它运行的顺序测试代码。
我还发现我无法制作所有标记的数组并立即加载它们,因此我将addMarker()
函数调整为仅采用一个标记,并在获取标记的循环内调用它数据。一旦我开始工作,我就能再次使HTTPClient调用异步。
答案 1 :(得分:0)
在Android上,任何从UI线程启动的任务,特别是网络活动,都需要与SDK 2.3异步。