5

Мы пишем код сервера в 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 

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

+0

почему вы не просто обеспечить обратный вызов fetchUser и испытания? Если вы хотите иметь более читаемый код, используйте обещания вместо обратных вызовов. – Tobi

+2

Вы не можете выполнять синхронные асинхронные операции. Невозможно сделать в Javascript. Перестань пытаться. Узнайте, как программировать асинхронно с обратными вызовами или обещаниями или переключиться на блокирующую/поточную среду, такую ​​как Java, которая позволяет делать такие вещи, как блокирование/синхронно в потоках (с соответствующими компрометациями этой архитектуры). – jfriend00

+0

Действительно новый для javascript. Иногда просто «просто невозможно» также является достаточно хорошим ответом. Благодарю. :) – Paagalpan

ответ

3

NodeJs однопоточный, поэтому мы не должны блокировать процесс.

в вашем случае у вас есть два варианта 1. прохождение обратного вызова 2. используя Promise библиотеку (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)

Ex 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: Использование библиотеки 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) 
      } 
     }); 
    }) 
} 

код клиента:

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

Спасибо за подробные примеры в обоих случаях. :) – Paagalpan

+0

[Parse Queries] (http://parseplatform.org/Parse-SDK-JS/api/classes/Parse.Query.html#methods_find) возвращает Parse.Обещание, которое почти полностью совместимо с Promises/A +, поэтому вам не нужно обертывать его в другую библиотеку Promise .... – simonberry

4

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

Также вы можете использовать promises или generators (с ECMAScript 6) подходы.

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

+0

Большое спасибо за ответ и отличный пример. И обновление было действительно полезно. Так что спасибо. Я не мог решить, какой ответ принять, но пошел с другим, поскольку у него был пример и для обещаний. Сожалею. – Paagalpan

Смежные вопросы