如何确保承诺链返回一个对象

时间:2016-09-20 18:01:11

标签: javascript parse-platform promise

我有这个函数,它有一连串的promises,我想返回一个对象:

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
}

该函数有两个if语句,我希望两者都返回'输出'我打电话时的对象:

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)
                  }
              })

'数据'对象应该是'输出' SignIn函数内的对象。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您应该将return放在user.fetchtokenData.save之前的if块中。在else阻止return之前放置Parse.promise.as

您当前的实现看起来与此类似。

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

在这两种情况下,您应将return放在somePromiseOnesomePromiseTwo之前,以便将data传递给承诺链。

答案 1 :(得分:0)

你可以做很多事情来整理东西......并让它发挥作用。

首先,您可以(并且应该)将代码从user.fetch({ success:... })回调移动到以下的回调中。当promise接口可用(并且已经使用)时,应该避免“Property-style”回调。

然后,您可以按如下方式进行流量控制:

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;
        });
    });
});

实际上,由于异步步骤的数量和同步代码的数量,代码将更加广泛,特别是在第一种情况下。

完整的,你最终会得到这样的东西:

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
            });
        });
    });
}