如何在使用 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() 函数相同的名称!