Как сделать синтаксический анализ операций поиска / сохранения?

Мы пишем код сервера в nodejs и используем Parse javascript sdk. Часто нам нужно выбрать или обновить различные объекты Parse. Например, получить пользователя с именем пользователя "Пример".

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

Эта функция может быть вызвана другой функцией:

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

Проблема в том, что я получил бы неопределенные результаты, потому что операции find/first выполняются асинхронно. Есть ли способ гарантировать, что функция fetchUser() вернется только тогда, когда операция поиска / первой успешна / завершена?

2 ответа

Решение

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

Код клиента:

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

Пример 2: Использование многообещающей библиотеки

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

Код клиента:

function test()
    {
      fetchUser("example")
        .then(function(user){
          console.log(user)  
        })
        .catch(function(error){
         console.error(error)
        })  
 }

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

Также вы можете использовать обещания или генераторы (начиная с EcmaScript 6).

UPD: Хотя некоторые API (драйверы БД, fs и т. Д.) Позволяют использовать их синхронно, это считается плохим способом написания кода на JavaScript. Поскольку JS запускает ваш код в одном потоке, блокировка этого потока с помощью синхронных вызовов блокирует все другие задачи. Таким образом, если вы разрабатываете веб-сервер, который обрабатывает несколько клиентов одновременно, и решили использовать синхронные вызовы для некоторого API, то будет обслуживаться только один клиент за раз, в то время как другие клиенты будут в состоянии ожидания.

Другие вопросы по тегам