当前位置: 动力学知识库 > 问答 > 编程问答 >

javascript - How to ensure the chain of promises return an object

问题描述:

I have this function that has a chain of promises and I want to return an object:

var signIn = function(fb_ID,fb_accessToken) {

console.log("signin!")

var promise = new Parse.Promise();

var TokenStorage = Parse.Object.extend("tokenStorage");

var query = new Parse.Query(TokenStorage);

query.equalTo('facebookID', fb_ID);

query.ascending('createdAt');

var password;

var username;

var output = {};

var user;

// Check if this ID has previously logged in, using the master key

return query.first({ useMasterKey: true }).then(function(tokenData) {

// Update the accessToken if it is different.

if (fb_accessToken !== tokenData.get('fb_accessToken')) {

console.log('1')

user = tokenData.get('user');

user.fetch({

success: function(data) {

username = data.get('username')

tokenData.set('fb_accessToken', fb_accessToken);

/*

password = new Buffer(24);

_.times(24, function(i) {

password.set(i, _.random(0, 255));

password = password.toString('base64')

})

*/

password = (Date.now().toString(36) + Math.random().toString(36).substr(2, 10)).toUpperCase();

user.setPassword(password);

tokenData.set('password',password)

console.log('fetch')

return

}

}).then(function(){

tokenData.save(null, { useMasterKey: true }).then(function(tokenuser) {

console.log('tokensave')

user.save();

return Parse.User.logIn(username, password);

}).then(function(data) {

// Return the user object.

console.log('output return')

output.success = true

output.isnewuser = false

output.username = username;

output.password = password;

output.fb_accessToken = fb_accessToken;

//return Parse.Promise.as(output);

//promise.resolve(output)

//return promise

return output

});

})

} else {

console.log('2')

Parse.Promise.as().then(function() {

username = tokenData.get('username');

password = tokenData.get('password');

return

}).then(function(){

return Parse.User.logIn(username, password)

.then(function(data) {

// Return the user object

output.success = true

output.isnewuser = false

output.username = username;

output.password = password;

output.fb_accessToken = fb_accessToken;

console.log('oo'+JSON.stringify(output))

//return Parse.Promise.as(output);

//promise.resolve(output)

return output

});

})

}

})

//return promise

}

The function has two if statements and I would like that both will return 'output' object when I call:

signIn(fb_ID,fb_accessToken).then(function(data){

if (data.success == true) {

console.log('inn'+JSON.stringify(data))

response.success(data)

}

else {

console.log('errr')

response.error(data)

}

})

The 'data' object should be the 'output' object inside the SignIn function. Any idea?

网友答案:

You should put return before user.fetch and tokenData.save in first if block. In the else block put return before Parse.promise.as.

Your current implementation looks like something similar to this.

var someFunction = function () {
        return mainPromise().then(function () {
            if (someCondition) {
                somePromiseOne().then(function () {
                    return data;
                });
            }
            else {
                somePromiseTwo().then(function () {
                    return data;
                });
            }
        });
    };

In the both cases you should put return before somePromiseOne and somePromiseTwo in order to pass the data to the promise chain.

网友答案:

You can do quite a lot to tidy things up ... and get it working.

First, you can (and should) move the code from the user.fetch({ success:... }) callback into the following then's callback. "Property-style" callbacks should be avoided when a promise interface is available (and already used).

Then, you might aim for flow control as follows :

doSomethingAsync().then(function() {
    var promise;
    if(condition) {
        promise = ...; // deliver username and password
    } else {
        promise = ...; // deliver username and password
    }
    return promise.then(function(details) {
        return login().then(function() {
            // fully compose output object here
            return details;
        });
    });
});

In practice, the code will be more extensive due to the number of async steps and the volume of synchronous code, particularly in the first condition.

In full, you might end up with something like this :

var signIn = function(fb_ID, fb_accessToken) {
    var query = new Parse.Query(Parse.Object.extend('tokenStorage'));
    query.equalTo('facebookID', fb_ID);
    query.ascending('createdAt');
    // Check if this ID has previously logged in, using the master key
    return query.first({ useMasterKey: true }).then(function(tokenData) {
        var promise;
        // Update the accessToken if it is different.
        if (fb_accessToken !== tokenData.get('fb_accessToken')) {
            var user = tokenData.get('user');
            promise = user.fetch().then(function(data) {
                var details = {
                    username: data.get('username'),
                    password: (Date.now().toString(36) + Math.random().toString(36).substr(2, 10)).toUpperCase()
                }; 
                tokenData.set('fb_accessToken', fb_accessToken);
                tokenData.set('password', details.password);
                user.setPassword(details.password);

                // Assuming here that `tokenData.save()` and `user.save()` are both async and can be executed in parallel.
                return Parse.Promise.when([
                    tokenData.save(null, { useMasterKey: true }),
                    user.save()
                ]).then(function() {
                    return details;
                });
            });
        } else {
            // here `promise` mimics the final successful state of the promise in the other condition.
            // ie. promise-wrapped details
            promise = Parse.Promise.as({
                username: tokenData.get('username'),
                password: tokenData.get('password')
            });
        }
        return promise.then(function(details) {
            // whichever condition was executed, username and password details are delivered here in an identical format.
            return Parse.User.logIn(details.username, details.password).then(function() {
                details.success = true;
                details.isnewuser = false;
                details.fb_accessToken = fb_accessToken;
                return details; // deliver details to signIn's caller
            });
        });
    });
}
分享给朋友:
您可能感兴趣的文章:
随机阅读: