Search code examples
javascriptasynchronoustitanium

Going crazy with async calls in Titanium


After spend 6 hours trying different approaches to my problem, I always get the same error and can't figure out why.

The problem is simple to understand: I have 10 users saved in Appcelerator Titanium ACS and I want to create 10 records, one for each user.

The stuff must be easy: all users have the same pass, so I only need to login with each one, create the object as the user and, thats all!! (In ACS, the objects are owned (and have user_id assigned automatically) by the user who creates them).

To manage async, I use functions with callback to wait till the end.

var Cloud = require('ti.cloud');

function createObject(value, onComplete) {
    Cloud.Objects.create({
        classname: 'MyObj',
        session_id: Cloud.sessionId,
        fields: {
            value: value
        }
    }, function(data) {
        if (data.success) {
            Ti.API.info('New value: user [' + data.Scores[0].user_id + '] - value: ' + data.Scores[0].value);
            onComplete(true);
        } else {
            Ti.API.info('Error: ' + data.message);
            onComplete(false);
        }
    });
}

function login(user, onComplete) {
    Cloud.Users.login({
        login: user.username,
        password: '1234'
    }, function(e) {
        if (e.success) {
            createObject(20, function(cb) {
                onComplete(true);
            });
        } else {
            Ti.API.warn('Error login user: ' + e.message);
            onComplete(false);
        }
    });
}

// Get target users
Cloud.Users.query({
    response_json_depth: 1
}, function(data) {
    if (data.success) {
        _.each(data.users, function(user) {
            login(user, function(cb) {
                Ti.API.warn("user: " + user.username);
            });
        });
    }
});

Well, my results are always the same:

Ti.API.warn('user: ' + user.username); shows the right users name (one by one), but Ti.API.info('New value: user [' + data.Scores[0].user_id + '] - value: ' + data.Scores[0].value); shows always the same user, meaning that all the values are saved for the same user (checked in DB, are all the same user), instead of 1 value per user.

I also tried to use async in the _.each command, but with the same results.

Where is the problem? I think I'm waiting in _.each user for the login, and the login must wait to finish the createObject, but seems I'm doing something wrong.

And here the exit. No sense for me...:

New value: user [54cb62cf18beba0935422a35] - value: 20
user: krusty
New value: user [54cb62cf18beba0935422a35] - value: 20
user: apu
New value: user [54cb62cf18beba0935422a35] - value: 20
user: ned

Note: the user_id saved for all calls correspond to user NED (the last)


Solution

  • It was a bug in ACS. Anyway, it doesn't matters currently, because was fixed 5 years ago.