简体   繁体   English

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

[英]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: 我有这个函数有一个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
}

The function has two if statements and I would like that both will return 'output' object when I call: 该函数有两个if语句,我希望在调用时它们都返回'output'对象:

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. 'data'对象应该是SignIn函数内的'output'对象。 Any idea? 任何想法?

You should put return before user.fetch and tokenData.save in first if block. 你应该把returnuser.fetchtokenData.save在第一if块。 In the else block put return before Parse.promise.as . else块把return之前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. 在这两种情况下,您应该在somePromiseOnesomePromiseTwo之前放置return ,以便将data传递给promise链。

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. 首先,您可以(并且应该)将代码从user.fetch({ success:... })回调移动到以下的回调中。 "Property-style" callbacks should be avoided when a promise interface is available (and already used). 当promise接口可用(并且已经使用)时,应该避免“Property-style”回调。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM