如何使解析查找/保存操作同步?

Paa*_*pan 6 javascript node.js promise parse-platform parse-javascript-sdk

我们在nodejs中编写服务器代码并使用Parse javascript sdk.我们经常需要获取或更新各种Parse对象.例如,使用用户名"Example"获取用户.

  function fetchUser(username)
  {
      var User = Parse.Object.extend("User");
      var query = new Parse.Query("User");
      query.equalTo("username",username);

      query.first({
        success: function(results) {
        console.log("Successfully retrieved " + results.length + " scores.");
        return results;
      },
      error: function(error) {
        console.log("Error: " + error.code + " " + error.message);
      }
     });
  }
Run Code Online (Sandbox Code Playgroud)

其他函数可能会调用此函数:

function test()
{
    var user = fetchUser("example");
    console.log(user); // would often print undefined
    return user;
}

function top()
{
    // some code
    var user = test();
    //some code
}

// and the function top() mmight be called by some other functions
Run Code Online (Sandbox Code Playgroud)

问题是我会得到未定义的结果,因为find/first操作是异步运行的.有没有办法确保fetchUser()函数仅在find/first操作成功/完成时返回?

Iva*_*hko 5

JavaScript本质上是异步的。您必须将回调传递给该fetchUser()函数,并将客户端代码重写为如下形式:

function fetchUser(username, callback) {
    // do request and call callback(null, user) on success
    // or callback(some_error_object) on failure.
}

function test(callback) {
    var onFetched = function(err, user) {
        console.log(user);
        callback(err, user);
    }
    var user = fetchUser("example", onFetched);
}
Run Code Online (Sandbox Code Playgroud)

你也可以使用承诺发电机(自EcmaScript的6)方法。

UPD:尽管某些API(数据库驱动程序,fs等)允许人们以同步方式使用它们,但将其视为用JavaScript编写代码的一种不好的方式。由于JS在单个线程中运行您的代码,因此通过使用同步调用阻止此线程将阻止所有其他任务。因此,如果您开发了一个可同时处理几个客户端的Web服务器,并决定使用对某些API的同步调用,则一次仅服务一个客户端,而其他客户端则处于待处理状态。


小智 3

NodeJs 是单线程的,所以我们不应该阻塞进程。

在你的情况下,你有两个选择1.传递回调2.使用Promise库(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

例 1:传递回调

    function fetchUser(username, callback)
  {
      var User = Parse.Object.extend("User");
      var query = new Parse.Query("User");
      query.equalTo("username",username);

      query.first({
        success: function(results) {
        console.log("Successfully retrieved " + results.length + " scores.");
        callback(null,results)
      },
      error: function(error) {
        console.log("Error: " + error.code + " " + error.message);
        callback(error)
      }
     });
  }
Run Code Online (Sandbox Code Playgroud)

客户端代码:

  function test()
    {
        var user = fetchUser("example", function(error, user){
         if(error){
          console.error(error)
         }else {
          console.log(user)
         }
      });
 }
Run Code Online (Sandbox Code Playgroud)

例 2:使用 Promising 库

  function fetchUser(username){
    return new Promise(function(resolve, reject){
        var User = Parse.Object.extend("User");
        var query = new Parse.Query("User");
        query.equalTo("username",username);

        query.first({
            success: function(results) {
                console.log("Successfully retrieved " + results.length + " scores.");
                resolve(results)
            },
            error: function(error) {
                console.log("Error: " + error.code + " " + error.message);
                reject(error)
            }
        });
    })
}
Run Code Online (Sandbox Code Playgroud)

客户端代码:

function test()
    {
      fetchUser("example")
        .then(function(user){
          console.log(user)  
        })
        .catch(function(error){
         console.error(error)
        })  
 }
Run Code Online (Sandbox Code Playgroud)