简体   繁体   English

Javascript似乎没有正确返回Parse对象

[英]Javascript doesn't seem to return Parse objects properly

I have a function called makeNewNode() that should take a Parse GeoPoint object and return a (custom) Parse object called node that contains a GeoPoint object with the key "location" and a pointer to another custom Parse object with the key "stop." 我有一个名为makeNewNode()的函数,该函数应该使用Parse GeoPoint对象并返回一个名为node的(自定义)Parse对象,该对象包含一个带有键“location”的GeoPoint对象和一个指向另一个自定义Parse对象的指针,其中键为“stop”。 “ What this function should do is essentially "snap" to a node if there is one within the SNAP_RADIUS of its GeoPoint. 如果节点的GeoPoint的SNAP_RADIUS中有一个节点,该功能应该基本上“捕捉”到节点。 If not, return a brand new node with a null "stop" pointer and a "location" of the parameter geoPoint . 如果没有,则返回一个带有“stop”指针和参数geoPoint “location”的全新节点。

I have a couple issues with this code. 我对这段代码有几个问题。

The first is that it seems to always fail to return anything. 首先是它似乎总是无法返回任何东西。 The Parse query always returns success, which is good. Parse查询总是返回成功,这很好。 However, it only returns something usable when it "snaps." 但是,它只会在“快照”时返回可用的内容。 Otherwise it just returns an undefined results variable. 否则它只返回一个未定义的results变量。

The second (and main) is that regardless of snapping or not, the function never returns anything remotely similar to the node object that I'm expecting. 第二个(也就是主要的)是无论是否捕捉,该函数都不会返回任何远程类似于我期望的节点对象的东西。 This leads me to believe through extensive use of console.log that node is never changed or affected by the actions within the success function of the query. 这使我相信通过广泛使用console.log ,该节点永远不会被查询的成功函数中的操作更改或影响。

The third is related to the previous in a more general sense. 第三个与更一般意义上的前一个相关。 Every time I've tried to return an object from a function in Javascript it hasn't acted the way I've expected. 每当我试图从Javascript函数返回一个对象时,它就没有按照我的预期行事。 Every time I've tried to change a variable from within a query's success function nothing actually changes. 每次我尝试从查询的成功函数中更改变量时,实际上没有任何变化。 I am a little new to this more in-depth Javascript as my previous experience has been a little more light. 我对这个更深入的Javascript有点新鲜,因为我之前的经验更加轻松。

This is the troublesome code. 这是麻烦的代码。

function makeNewNode(geoPoint) {
  var node = {};
  var Node = Parse.Object.extend("Nodes");
  var query = new Parse.Query(Node);
  query.withinMiles("location",geoPoint,SNAP_RADIUS);
  query.first({
    success: function(results) {
      console.log(results);
      console.log(results + "");
      if (results == undefined) {
        node = new Node();
        node.set("location",geoPoint);
        node.set("stop",null);
        node.save();
        console.log(node.id);
      } else {
        node = results;
      }
    },
    error: function(error) {
      console.log("Failed to create a node. Error: " + error.message + ".");
    }
  });
  return node;
}

And here is where I call it. 这就是我所说的。

var geoPoint = new Parse.GeoPoint(location.lat(),location.lng());
var newnode = makeNewNode(geoPoint);

Any ideas or suggestions about my code or either of the three questions is greatly appreciated. 任何有关我的代码或三个问题之一的想法或建议都非常感谢。

A cleaner way is to use promises, so that the save of the newly created object can be handled without the extra callback parameter and without creating deeper and deeper nesting of success functions. 更简洁的方法是使用promises,这样就可以在没有额外回调参数的情况下处理新创建的对象的保存,并且不会创建更深入和更深的成功函数嵌套。 Moreover, the caller may want to make a node as part of some larger set of asynch steps. 此外,调用者可能希望将节点作为一组更大的异步步骤的一部分。

A promise version looks like this: 承诺版本如下所示:

// return a promise that, when fulfilled, creates a new node with
// at the geoPoint, or, if a node exists within SNAP_RADIUS, returns that node
function makeNewNode(geoPoint) {
    var Node = Parse.Object.extend("Nodes");
    var query = new Parse.Query(Node);
    query.withinMiles("location",geoPoint,SNAP_RADIUS);
    return query.first().then(function(node) {
        if (!node) {
            node = new Node();
            node.set("location", geoPoint);
            node.set("stop", null);
        }
        return (node.isNew())? node.save() : Parse.Promise.as(node);
    });
}

The caller can now chain this with other promises. 调用者现在可以将其与其他承诺链接起来。

EDIT - Here's how you call it. 编辑 - 这就是你如何称呼它。 Lets say we get the geoPoint in another asynchronous call, then... 让我们说我们在另一个异步调用中得到geoPoint,然后......

var geoPoint = new Parse.GeoPoint(location.lat(),location.lng());
makeNewNode(geoPoint).then(function(newNode) {
    console.log("new node id is " + newNode.id);
}, function(error) {
    console.log("error " + error.message);
});

What's up with all the returns? 所有的回报是什么? A promise is a placeholder for the result. 承诺是结果的占位符。 Returning it gives the caller and object to which they can attach a completion function (using the then() method). 返回它给调用者和对象提供了一个完成函数(使用then()方法)。 That completion callback can also return a promise (that's the inner return), so that they can be chained arbitrarily. 完成回调也可以返回一个promise(这是内部返回),这样它们就可以被任意链接。 The second parameter to then() is an optional callback to handle failure. then()的第二个参数是一个可选的回调函数来处理失败。

I don't know if you are aware of the async issues, but they might be the problem. 我不知道您是否了解异步问题,但它们可能是问题所在。

function makeNewNode(geoPoint) {
  var Node = Parse.Object.extend("Nodes");
  var node = new Node();
  var query = new Parse.Query(Node);
  query.withinMiles("location",geoPoint,SNAP_RADIUS);
  query.first({
    success: function(results) {
      console.log(results);
      console.log(results + "");
      if (results == undefined) {
        node.set("location",geoPoint);
        node.set("stop",null);
        node.save(function() {
          console.log(node.id);
        });
      } else {
        node.set("location", results.get("location"));
        node.set("stop", results.get("stop"));
      }
    },
    error: function(error) {
      console.log("Failed to create a node. Error: " + error.message + ".");
    }
  });
  return node;
}

query.first() is an async function. query.first()是一个异步函数。 When your function returns, the async function may have not called your callback. 当您的函数返回时,异步函数可能没有调用您的回调。 In this situation, the return value would be the object {} as you defined at the beginning. 在这种情况下,返回值将是您在开头定义的对象{}

Later when you assign a new value( new Node() and so) to node , the returned value would still be the previous object, instead of the new object assigned to node . 当你将一个新的值(后来new Node()等),以node ,返回值仍然是以前的对象,而不是分配给新的对象node

The simple fix would be to use a pre-assigned object for returning, and update its content later, just like my example above. 简单的解决方法是使用预先指定的对象进行返回,并在以后更新其内容,就像上面的示例一样。

However, this is never a good solution for an async code snippet. 但是,对于异步代码段,这绝不是一个好的解决方案。 You should use either a callback or a promise to return the new Node . 您应该使用回调或承诺来返回新Node

Using a callback would be like: 使用回调就像:

function makeNewNode(geoPoint, callback) {
  var Node = Parse.Object.extend("Nodes");
  var node;
  var query = new Parse.Query(Node);
  query.withinMiles("location",geoPoint,SNAP_RADIUS);
  query.first({
    success: function(results) {
      console.log(results);
      console.log(results + "");
      if (results == undefined) {
        node.set("location", geoPoint);
        node.set("stop", null);
        node.save(function() {
          console.log(node.id);
          callback(null, node);
        });
      } else {
        callback(null, results);
      }
    },
    error: function(error) {
      console.log("Failed to create a node. Error: " + error.message + ".");
      callback(error);
    }
  });
}

And you would be able to use it like: 你可以像以下一样使用它:

makeNewNode(geoPoint, function(err, newNode) {
  // use your new Node here.
})

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

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