Как сделать синтаксический анализ операций поиска / сохранения?
Мы пишем код сервера в 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, то будет обслуживаться только один клиент за раз, в то время как другие клиенты будут в состоянии ожидания.