如何在使用 Appcelerator 进入 Android 中的下一个循环之前等待函数完成
How to wait for a function to complete before moving to next in loop in Android using Appcelerator
所以我有一个从 API.
预加载图形的应用程序
我首先从我的板载数据库中获取我需要的所有数据,遍历它并将用户发送到一个函数来下载图像、调整图像大小等。
在 iOS 这似乎很好用,但是在 Android 它总是掉下来。
我正在寻找一种不会使应用程序崩溃的更优雅的方法。
有没有一种方法可以等待 getMarker()
函数完成,然后我的循环(从 getMapMarkers()
函数)向它发出另一个请求?
这是我应用程序那部分的代码片段。函数 getMarker()
处理图像和调整大小。
function getMarker(url, filename) {
var mapMarker = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map_marker_icons', filename);
// now we need to download the map marker and save it into our device
var getMarker = Titanium.Network.createHTTPClient({
timeout: 30000
});
getMarker.onload = function() {
// if the file loads, then write to the filesystem
if (getMarker.status == 200) {
var image = this.responseData;
// resize to 75 pixel marker
var resizedImage = image.imageAsResized(75, 75);
mapMarker.write(resizedImage);
//I ALWAYS NULL ANY PROXIES CREATED SO THAT IT CAN BE RELEASED
image = null;
resizedImage = null;
mapMarker = null;
} else {
Ti.API.info("Image not loaded");
}
//getMarker = null;
};
getMarker.onerror = function(e) {
Ti.API.info('XHR Error ' + e.error);
//alert('markers data error');
};
getMarker.ondatastream = function(e) {
if (e.progress == 1) {
Ti.API.info(filename + ' Download Complete');
}
};
// open the client
getMarker.open('GET', url);
// send the data
getMarker.send();
}
function getMapMarkers() {
// get the species list back
var db = Ti.Database.open('myDB');
var getSpeciesImages = db.execute('SELECT speciesiconfilename, speciesmapiconurl FROM species where speciesiconfilename <> ""');
// YOU ONLY NEED TO DO THIS ONCE SO DO IT OUTSIDE THE LOOP
var imgDir = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map_marker_icons');
// if the directory doesn't exist, then we need to create it
if (!imgDir.exists()) {
// If the directory doesn't exist, make it
imgDir.createDirectory();
};
// start the loop
while (getSpeciesImages.isValidRow()) {
var filename = getSpeciesImages.fieldByName('speciesiconfilename');
var url = getSpeciesImages.fieldByName('speciesmapiconurl');
getMarker(url, filename);
getSpeciesImages.next();
} // end the loop
getSpeciesImages.close();
// close the database
db.close();
// get the exhibit markers next
getExhibitMapMarkers();
};
有人能帮忙吗?这让我发疯!
西蒙
js 问题多于 titanium。对于这些事情,我更喜欢使用 Q 库 (https://github.com/kriskowal/q)。
function getMarker(url, filename) {
return function() {
var defered = Q.defer();
...
var xhr = Titanium.Network.createHTTPClient({
timeout: 30000
});
xhr.onload = function() {
...
defered.resolve();
};
xhr.onerror = function(e) {
...
defered.resolve(); // or defered.reject() if you want stop after first error
}
...
xhr.open('GET', url);
xhr.send();
return defered.promise;
};
}
function getMapMarkers() {
...
var imageRequests = [];
while(getSpeciesImages.isValidRow()) {
...
imageRequests.push(getMarker(url, filename));
getSpeciesImages.next();
}
imageRequests.reduce(Q.when, Q(true))
.then(function() {
Ti.API.info('all loaded');
});
...
};
并且不要将 http 客户端变量命名为与 getMarker() 函数相同的名称!
所以我有一个从 API.
预加载图形的应用程序我首先从我的板载数据库中获取我需要的所有数据,遍历它并将用户发送到一个函数来下载图像、调整图像大小等。
在 iOS 这似乎很好用,但是在 Android 它总是掉下来。
我正在寻找一种不会使应用程序崩溃的更优雅的方法。
有没有一种方法可以等待 getMarker()
函数完成,然后我的循环(从 getMapMarkers()
函数)向它发出另一个请求?
这是我应用程序那部分的代码片段。函数 getMarker()
处理图像和调整大小。
function getMarker(url, filename) {
var mapMarker = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map_marker_icons', filename);
// now we need to download the map marker and save it into our device
var getMarker = Titanium.Network.createHTTPClient({
timeout: 30000
});
getMarker.onload = function() {
// if the file loads, then write to the filesystem
if (getMarker.status == 200) {
var image = this.responseData;
// resize to 75 pixel marker
var resizedImage = image.imageAsResized(75, 75);
mapMarker.write(resizedImage);
//I ALWAYS NULL ANY PROXIES CREATED SO THAT IT CAN BE RELEASED
image = null;
resizedImage = null;
mapMarker = null;
} else {
Ti.API.info("Image not loaded");
}
//getMarker = null;
};
getMarker.onerror = function(e) {
Ti.API.info('XHR Error ' + e.error);
//alert('markers data error');
};
getMarker.ondatastream = function(e) {
if (e.progress == 1) {
Ti.API.info(filename + ' Download Complete');
}
};
// open the client
getMarker.open('GET', url);
// send the data
getMarker.send();
}
function getMapMarkers() {
// get the species list back
var db = Ti.Database.open('myDB');
var getSpeciesImages = db.execute('SELECT speciesiconfilename, speciesmapiconurl FROM species where speciesiconfilename <> ""');
// YOU ONLY NEED TO DO THIS ONCE SO DO IT OUTSIDE THE LOOP
var imgDir = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map_marker_icons');
// if the directory doesn't exist, then we need to create it
if (!imgDir.exists()) {
// If the directory doesn't exist, make it
imgDir.createDirectory();
};
// start the loop
while (getSpeciesImages.isValidRow()) {
var filename = getSpeciesImages.fieldByName('speciesiconfilename');
var url = getSpeciesImages.fieldByName('speciesmapiconurl');
getMarker(url, filename);
getSpeciesImages.next();
} // end the loop
getSpeciesImages.close();
// close the database
db.close();
// get the exhibit markers next
getExhibitMapMarkers();
};
有人能帮忙吗?这让我发疯!
西蒙
js 问题多于 titanium。对于这些事情,我更喜欢使用 Q 库 (https://github.com/kriskowal/q)。
function getMarker(url, filename) {
return function() {
var defered = Q.defer();
...
var xhr = Titanium.Network.createHTTPClient({
timeout: 30000
});
xhr.onload = function() {
...
defered.resolve();
};
xhr.onerror = function(e) {
...
defered.resolve(); // or defered.reject() if you want stop after first error
}
...
xhr.open('GET', url);
xhr.send();
return defered.promise;
};
}
function getMapMarkers() {
...
var imageRequests = [];
while(getSpeciesImages.isValidRow()) {
...
imageRequests.push(getMarker(url, filename));
getSpeciesImages.next();
}
imageRequests.reduce(Q.when, Q(true))
.then(function() {
Ti.API.info('all loaded');
});
...
};
并且不要将 http 客户端变量命名为与 getMarker() 函数相同的名称!