真的很困惑:如何在云代码中正确使用解析承诺 [英] Really confused re: how to use Parse Promises correctly in Cloud Code

查看:62
本文介绍了真的很困惑:如何在云代码中正确使用解析承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不想将各种功能嵌套在成功完成处理程序中,而是想将我的功能分开,以便它们可以独立使用或连续使用.但是,我对Parse中的Promise语法感到非常困惑,尽管查看了许多其他StackOverflow答案(例如,此处此处文档概述和<有关该主题的href ="http://blog.parse.com/learn/engineering/whats-so-great-about-javascript-promises/" rel ="nofollow noreferrer">博客文章.

以下是我的云代码示例,在该示例中,我尝试使用链接的诺言:

Parse.Cloud.beforeSave(Parse.User, function(request, response) {
    var account = request.object;
    if (account.existed()) {
        if (account.dirtyKeys().indexOf("username") >= 0) {
            updateUsernameForAccountId(account.get("username"), account.id)
                .then(
                    function() {
                        console.log("Checkpoint SUCCESS");
                        response.success();
                    }, function(error) {
                        console.log("Checkpoint ERROR");
                        response.error(error);
                    });
        }
    }
});

function updateUsernameForAccountId(username, accountId) {
    console.log("Checkpoint A-1 ("+username+", "+accountId+")");
    updateUsernameForMessagesSentByAccountId(username, accountId)
        .then(
            function() {
                console.log("Checkpoint A-2");
                return updateUsernameForMessagesReceivedByAccountId(username, accountId);
            })
        .then(
            function() {
                console.log("Checkpoint A-3");
                return Parse.Promise.as();
            }, function(error) {
                console.log("Checkpoint A-ERROR");
                return Parse.Promise.error(error);
            });
};

function updateUsernameForMessagesSentByAccountId(username, accountId) {
    console.log("Checkpoint B-1");
    var query = new Parse.Query(parseClassMessage);
    query.equalTo(parseKeySenderId, accountId);
    query.find()
        .then(
            function(results) {
                console.log("Checkpoint B-2");
                var object;
                for (var i = 0; i < results.length; i++) {
                    console.log("Checkpoint B-2-"+i);
                    object = results[i];
                    object.set(parseKeySenderUsername, username);
                }
                return Parse.Promise.as(results);
            })
        .then(
            function(objects) {
                console.log("Checkpoint B-3");
                return Parse.Object.saveAll(objects);
            })
        .then(
            function() {
                console.log("Checkpoint B-4");
                return Parse.Promise.as();
            }, function(error) {
                console.log("Checkpoint B-ERROR");
                return Parse.Promise.error(error);
            });
};

function updateUsernameForMessagesReceivedByAccountId(username, accountId) {
    console.log("Checkpoint C-1");
    var query = new Parse.Query(parseClassMessage);
    query.equalTo(parseKeyRecipientId, accountId);
    query.find()
        .then(
            function(results) {
                console.log("Checkpoint C-2");
                var object;
                for (var i = 0; i < results.length; i++) {
                    console.log("Checkpoint C-2-"+i);
                    object = results[i];
                    object.set(parseKeyRecipientUsername, username);
                }
                return Parse.Promise.as(results);
            })
        .then(
            function(objects) {
                console.log("Checkpoint C-3");
                return Parse.Object.saveAll(objects);
            })
        .then(
            function() {
                console.log("Checkpoint C-4");
                return Parse.Promise.as();
            }, function(error) {
                console.log("Checkpoint C-ERROR");
                return Parse.Promise.error(error);
            });
};

预期的行为是:

  • 在保存User对象之前,请检查该对象是否已存在(相对于新创建的User)以及用户名是否已更改.
  • 如果是:执行功能updateUsernameForAccountId(username, accountId),先执行updateUsernameForMessagesSentByAccountId(username, accountId),然后执行updateUsernameForMessagesReceivedByAccountId(username, accountId).
    • 我不需要这两种方法是同步的,但是我认为有必要将单个Promise对象返回到beforeSave.

我能够成功将此代码上传到Cloud Code,但是当我进入Parse.com上的数据浏览器并更改要测试的现有User对象的用户名时,日志将产生以下输出:

E2015-08-11T21:16:23.467Z]v27 before_save triggered for _User as master:
  Input: {"original":{"createdAt":"2015-08-09T16:53:47.194Z","objectId":"mkTluyGbHf","updatedAt":"2015-08-11T17:23:19.523Z","username":"oldname@example.com"},"update":{"username":"newname@example.com"}}
  Result: TypeError: Cannot call method 'then' of undefined
    at updateUsernameForAccountId (main.js:114:4)
    at main.js:16:4
I2015-08-11T21:16:23.533Z]Checkpoint A-1 (newname@example.com, mkTluyGbHf)
I2015-08-11T21:16:23.534Z]Checkpoint B-1

而且我在Parse.com数据浏览器中也收到以下错误:

Error: TypeError: Cannot call method 'then' of undefined at updateUsernameForAccountId (main.js:114:4) at main.js:16:4

请让我知道我可以提供的其他信息或说明.我向您致歉,因为我无法更清楚地表达我的问题,错误或困惑.

解决方案

我自己解决了!!

问题是,正如错误明确指出的那样,我的方法updateUsernameForAccountId没有返回Promise对象.但是,问题出在updateUsernameForMessagesSentByAccountIdupdateUsernameForMessagesReceivedByAccountId之内,因为执行query.find()是异步方法,因此不会立即返回其完成处理程序中的任何内容.

要使函数返回Promise,您必须return Promise.

所以答案是要确保return query.find().

Instead of nesting various functions within success completion handlers, I'd like to separate out my functions so that they can either be used independently or in succession. However, I'm super confused regarding the syntax of promises in Parse and have not been able to chain them together successfully despite looking at many other StackOverflow answers (e.g., here, here, here, and here) and Parse's official documentation, overview, and blog post about the topic.

Here's an example of my Cloud Code where I am trying to use chained promises:

Parse.Cloud.beforeSave(Parse.User, function(request, response) {
    var account = request.object;
    if (account.existed()) {
        if (account.dirtyKeys().indexOf("username") >= 0) {
            updateUsernameForAccountId(account.get("username"), account.id)
                .then(
                    function() {
                        console.log("Checkpoint SUCCESS");
                        response.success();
                    }, function(error) {
                        console.log("Checkpoint ERROR");
                        response.error(error);
                    });
        }
    }
});

function updateUsernameForAccountId(username, accountId) {
    console.log("Checkpoint A-1 ("+username+", "+accountId+")");
    updateUsernameForMessagesSentByAccountId(username, accountId)
        .then(
            function() {
                console.log("Checkpoint A-2");
                return updateUsernameForMessagesReceivedByAccountId(username, accountId);
            })
        .then(
            function() {
                console.log("Checkpoint A-3");
                return Parse.Promise.as();
            }, function(error) {
                console.log("Checkpoint A-ERROR");
                return Parse.Promise.error(error);
            });
};

function updateUsernameForMessagesSentByAccountId(username, accountId) {
    console.log("Checkpoint B-1");
    var query = new Parse.Query(parseClassMessage);
    query.equalTo(parseKeySenderId, accountId);
    query.find()
        .then(
            function(results) {
                console.log("Checkpoint B-2");
                var object;
                for (var i = 0; i < results.length; i++) {
                    console.log("Checkpoint B-2-"+i);
                    object = results[i];
                    object.set(parseKeySenderUsername, username);
                }
                return Parse.Promise.as(results);
            })
        .then(
            function(objects) {
                console.log("Checkpoint B-3");
                return Parse.Object.saveAll(objects);
            })
        .then(
            function() {
                console.log("Checkpoint B-4");
                return Parse.Promise.as();
            }, function(error) {
                console.log("Checkpoint B-ERROR");
                return Parse.Promise.error(error);
            });
};

function updateUsernameForMessagesReceivedByAccountId(username, accountId) {
    console.log("Checkpoint C-1");
    var query = new Parse.Query(parseClassMessage);
    query.equalTo(parseKeyRecipientId, accountId);
    query.find()
        .then(
            function(results) {
                console.log("Checkpoint C-2");
                var object;
                for (var i = 0; i < results.length; i++) {
                    console.log("Checkpoint C-2-"+i);
                    object = results[i];
                    object.set(parseKeyRecipientUsername, username);
                }
                return Parse.Promise.as(results);
            })
        .then(
            function(objects) {
                console.log("Checkpoint C-3");
                return Parse.Object.saveAll(objects);
            })
        .then(
            function() {
                console.log("Checkpoint C-4");
                return Parse.Promise.as();
            }, function(error) {
                console.log("Checkpoint C-ERROR");
                return Parse.Promise.error(error);
            });
};

The expected behavior is:

  • Right before saving a User object, check if it is an already existing User (v. a newly created User) and whether the username was changed.
  • IF YES: Perform function updateUsernameForAccountId(username, accountId), which performs updateUsernameForMessagesSentByAccountId(username, accountId) and then updateUsernameForMessagesReceivedByAccountId(username, accountId).
    • N.b. I don't need these two methods to be synchronous, but I thought it necessary in order to return a single Promise object back to beforeSave.

I am able to upload this code to Cloud Code successfully, but when I go into the data browser on Parse.com and change the username of an existing User object to test, the log produces the following output:

E2015-08-11T21:16:23.467Z]v27 before_save triggered for _User as master:
  Input: {"original":{"createdAt":"2015-08-09T16:53:47.194Z","objectId":"mkTluyGbHf","updatedAt":"2015-08-11T17:23:19.523Z","username":"oldname@example.com"},"update":{"username":"newname@example.com"}}
  Result: TypeError: Cannot call method 'then' of undefined
    at updateUsernameForAccountId (main.js:114:4)
    at main.js:16:4
I2015-08-11T21:16:23.533Z]Checkpoint A-1 (newname@example.com, mkTluyGbHf)
I2015-08-11T21:16:23.534Z]Checkpoint B-1

And I also receive the following error in the Parse.com data browser:

Error: TypeError: Cannot call method 'then' of undefined at updateUsernameForAccountId (main.js:114:4) at main.js:16:4

Please let me know what additional information or clarification I can provide. I apologize in advance that I am not able to articulate my question, errors, or confusions more clearly.

解决方案

I solved it myself!!

The issue was that, as the error clearly stated, my method updateUsernameForAccountId wasn't returning a Promise object. However, the issue was within updateUsernameForMessagesSentByAccountId and updateUsernameForMessagesReceivedByAccountId, as executing query.find() is an asynchronous method and so will not return whatever is in its completion handler immediately.

In order for a function to return a Promise...you must return a Promise.

And so the answer was to make sure to return query.find().

这篇关于真的很困惑:如何在云代码中正确使用解析承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆