从云代码函数返回基于 objectId 的 Parse.User 对象列表

Posted

技术标签:

【中文标题】从云代码函数返回基于 objectId 的 Parse.User 对象列表【英文标题】:Returning list of Parse.User objects based on objectId from Cloud Code Function 【发布时间】:2015-08-18 15:00:06 【问题描述】:

这是我的云代码功能:

Parse.Cloud.define("nearby", function (request, response) 
    nearby(request.params.sourceId, 
      success: function(answer) 
          var values = Object.keys(answer.end_result).map(function(key) 
              nearby = answer.end_result[key];

              nearby.near = new Parse.User(id:nearby.nearId)

              return nearby;
          );

          response.success(values);
      ,
      error: function(error) 
        response.error(error);
      
    );
)

从 REST API 调用它

curl -X POST   -H "X-Parse-Application-Id: ..."  -H "X-Parse-REST-API-Key: ..."  -H "Content-Type: application/json"  -d ' "sourceId": "jQsulDGk8Z" '  https://api.parse.com/1/functions/nearby | python -m json.tool

按预期返回 JSON:


    "result": [
        
            "distance": 3,
            "near": 
                "__type": "Object",
                "className": "_User",
                "objectId": "aPWY5YP89A"
            ,
            "nearId": "aPWY5YP89A",
            "sourceId": "jQsulDGk8Z",
            "updateAt": 
                "__type": "Date",
                "iso": "2015-08-18T14:48:28.344Z"
            
        ,
        
            "distance": 2,
            "near": 
                "__type": "Object",
                "className": "_User",
                "objectId": "GHm78KVb9r"
            ,
            "nearId": "GHm78KVb9r",
            "sourceId": "jQsulDGk8Z",
            "updateAt": 
                "__type": "Date",
                "iso": "2015-08-18T14:48:22.738Z"
            
        
    ]

我怎样才能返回完全填充的用户对象,而不仅仅是在代码中创建的指针?由于 Parse.User 查询是异步的,当您有多个可变数量的用户 objectId 可供查询时,简单地阻止并等待对象填充是行不通的。

我需要对所有可能的用户查询进行某种同步。

【问题讨论】:

您已将问题标记为 promise,那么您是否尝试过使用它们? @Wain 您能否提供一个示例代码,说明如何为这个用例提供 Promise? 请出示function nearby()的出处。需要看看它是否返回一个承诺。另外,请在nearby中描述正在查询的数据。列名和类型(重要:该表中是否有指向 _User 的指针?) @danh 这里是部署在云代码gist.github.com/maximveksler/59f95a4a66232df51eed 中的当前版本的实际复制和粘贴。附近表的结构可能会发生变化,将源和附近作为引用而不是指针将有助于解决问题吗? 【参考方案1】:

好消息是您的NearBy 模型包含指向用户表的指针。该指针的结尾可以通过include-ing 在NearBy 查询中急切获取...

function queryNearby(userId, sourceColumn, nearColumn, callback) 
    var query = new Parse.Query(NearBy);
    query.include("near");
    // ...

还有一些不那么令人高兴的消息,但并非立即不高兴:如果需要另一个查询(或另一个异步操作),那么在 2-3 级回调间接构建它时会很头疼。你关于承诺的想法是正确的。考虑重构您的函数以始终返回 Promise 并使用从其 SDK 返回的 parse 的 Promise。

编辑为了详细说明 Promise 的使用,这里有一个修改为使用 Promise 的代码示例。

我们的想法是,我们拥有创建和返回 Promise 的函数,而不是传递回调函数和嵌套调用 N 层以进行 N 次后续异步操作。

现在函数nearby返回一个promise,因为它返回了函数queryNearBySourceId返回的promise。如果您进一步遵循该链,该函数也会返回一个承诺。最终,函数 findNearby 返回由 Parse.Query.find() 返回的承诺。注意没有函数传递或调用回调函数。

// call this function like this:
// nearby("some_source_id").then(function(result) , function(error) );
// the result passed to the resolution function will be the object returned by nearby()

function nearby(sourceId) 
    return queryNearBySourceId(sourceId).then(function(answer) 
        // see the end of function queryNearby: I modified it to answer a single object
        var nearbyId_answer = answer;
        var nearId_runtime = answer.runtime_seen_updates;
        var end_result = 

        _.each(sourceId_answer, function(value, key) 
            end_result[key] = value
        );

        _.each(nearbyId_answer, function(value, key) 
            if (!(key in end_result)) 
                end_result[key] = value
            
        );

        return "end_result" : end_result, 
                "sourceId_answer" : sourceId_answer, 
                "sourceId_runtime" : sourceId_runtime, 
                "nearbyId_answer" : nearbyId_answer, 
                "nearId_runtime" : nearId_runtime
                ;
    );


function queryNearBySourceId(sourceId) 
    // console.error("******** queryNearby -- queryNearBySourceId")
    return queryNearby(sourceId, "source", "near")


function queryNearByNearId(nearId) 
    // console.error("******** queryNearby -- queryNearByNearId")
    return queryNearby(nearId, "near", "source")


function queryNearby(userId, sourceColumn, nearColumn) 
    // console.error("queryNearby(" + userId + "," + sourceColumn + "," + nearColumn + ")")
    var user = new Parse.User(id:userId);
    var lastValid = moment().subtract(5, 'minutes').toDate();
    return findNearby(user, lastValid, nearColumn).then(function(results) 
        // Model:  near : distance 
        var answer = 
        // Model:  near : updateAt 
        var runtime_seen_updates = 

        for (var i = 0; i < results.length; i++) 
            var nearby_entry = results[i];
            var source = nearby_entry.get(sourceColumn)
            var sourceId = source.id
            var distance = nearby_entry.get("distance")
            var updateAt = nearby_entry.updatedAt
            var o =  "sourceId" : sourceId, "near" : near, "distance" : distance, "updateAt" : updateAt 

            // console.error("queryNearby :: " + JSON.stringify(o))

            // Our goal is to find the most recent entry
            if (nearId in runtime_seen_updates) 
                // console.error("queryNearby (in runtime_seen_updates) :: " + nearId + "=" + JSON.stringify(o))
                runtime_seen_updates_updateAt = runtime_seen_updates[nearId]
                if (runtime_seen_updates_updateAt < updateAt) 
                    runtime_seen_updates[nearId] = updateAt
                    answer[nearId] = o
                
             else 
                // console.error("queryNearby (first) :: " + nearId + "=" + JSON.stringify(o))
                runtime_seen_updates[nearId] = updateAt
                answer[nearId] = o
            
        
        // rather than returning two objects, I added the 'runtime_seen_updates' attribute to the answer object
        answer.runtime_seen_updates = runtime_seen_updates;

        return answer;
    , function(error) 
        alert("Error: " + error.code + " " + error.message);
        return error;
    );


function findNearby(user, date, nearColumn) 
    var query = new Parse.Query(NearBy);    
    query.equalTo(sourceColumn, user); // be we search which devices saw us.
    query.greaterThan("updatedAt", date);
    query.descending("updatedAt");
    query.include(nearColumn);  // important!
    return query.find();
 

在编辑时,我注意到了一些进一步改进此代码的方法,但我将自己限制在为 promise 进行重构,因为我希望您认识到原始代码中的单一想法变化。

【讨论】:

您能否提供一个实现承诺的自定义函数的示例?我并不是说像 parse 文档这样的东西提供了他们通过回调设置超时的地方,而是一些执行计算逻辑的东西。我返回一个承诺,然后去做一些工作,然后解决这个承诺。重写我自己的代码,或者参考其他人的代码来显示这一点也很棒。 tnx. @MaximVeksler - 我尝试在您的代码中说明这个想法。我建议将其与原件并列进行审查。还可以查看 parse 的 promise 指南 (parse.com/docs/js/guide#promises)。一旦你掌握了这个窍门,你就再也不想写(或读)传统的回调代码了。 感谢@danh 我确实阅读了所有关于 Promises 的 parse 文档,并且我知道 find() 返回一个 Promise,它可以用作返回值。我的问题是用一个承诺重新实现 queryNearby:如果我可以从 queryNearby 返回一个承诺 完成工作,然后执行 Promise.resolved() 那么一切都会变得更简单。感谢您编辑我的代码,但我认为您错过了对 queryNearByNearId() 的第二次调用,这对我的逻辑至关重要,而且我相信演示代码旨在显示使用 include() 获取 Parse.User 对象? @MaximVeksler,github 代码显示了对 queryNearByNearId 的单个调用。我没有看到第二个电话。我如此参与您的代码,我忘记了我的答案的要点是包含()!现在将对其进行编辑。回顾一下:这里的问题是如何检索指向的用户,而答案——我认为是正确的——是使用 include()。我顺便提到过,promise 是一种更好的组织代码的方式,并且花了一些时间将你的代码重构为一个 Promise 教程。我认为它是正确的(或接近),但重点是:使用承诺。

以上是关于从云代码函数返回基于 objectId 的 Parse.User 对象列表的主要内容,如果未能解决你的问题,请参考以下文章

无法从云形成 yaml 中的条件函数返回整数

从云计算到函数计算

通过云函数从云存储中读取数据

分析函数之开窗函数over

云函数可以从云存储中读取吗?

R语言中绘图par()函数用法