NodeJS с arangojs и синхронизацией: все после .sync() игнорируется?

Я хочу использовать NodeJS для чтения 60 тыс. записей из базы данных MySQL и записи их в базу данных ArangoDB. Позже я буду использовать функции агрегации ArangoDB и т. д. для обработки моего набора данных.

Исходя из PHP, где скрипт обычно выполняется синхронно, и поскольку я считаю, что здесь это имеет смысл, моя первоначальная (наивная) попытка заключалась в том, чтобы мой скрипт NodeJS также выполнялся синхронно. Однако это не работает так, как ожидалось:

Я печатаю на консоль, вызываю функцию через .sync() для подключения к серверу ArangoDB и печатаю все существующие базы данных, затем снова печатаю на консоль. Но все, что находится ниже вызова синхронизации для моей функции ArangoDB, полностью игнорируется (не выводится снова на консоль и, похоже, здесь ничего не выполняется).

Что я упускаю из виду? .done() в функции, вызываемой через .sync(), вызывает проблемы?

var mysql = require('node-mysql');
var arango = require('arangojs');
//var sync = require('node-sync'); // Wrong one!
var sync = require('sync');


function test_arango_query() {
    var db = arango.Connection("http://localhost:8529");
    db.database.list().done(function(res) {
        console.log("Databases: %j", res);
    });
    return "something?";
}

sync(function() {
    console.log("sync?");
    var result = test_arango_query.sync();
    console.log("done."); // DOES NOT PRINT, NEVER EXECUTED?!
    return result;

}, function(err, result) {
    if (err) console.error(err);
    console.log(result);
});

person CodeManX    schedule 08.05.2014    source источник


Ответы (1)


Ваша функция test_arango_query не использует обратный вызов. sync работает только с функциями, использующими обратный вызов. Он должен знать, когда данные будут готовы вернуть их из .sync(), если ваша функция никогда не вызывает обратный вызов, то sync никогда не сможет вернуть результат.

Обновите свою функцию, чтобы вызывать функцию обратного вызова, когда вы хотите, чтобы она возвращалась:

function test_arango_query(callback) {
    var db = arango.Connection("http://localhost:8529");
    db.database.list().done(function(res) {
        console.log("Databases: %j", res);
        callback('something');
    });
}
person Paul    schedule 08.05.2014
comment
Имеет смысл и было одним простым решением. Большое спасибо! Ваше объяснение должно быть первым абзацем sync файла readme. Кажется, не хватает очень простых примеров, которые фокусируются на основной концепции. - person CodeManX; 09.05.2014
comment
Однако мне интересно, почему NodeJS завершает работу сразу после запроса arangodb с использованием моего исходного кода. Если моя функция test_arango_query() никогда не возвращается и она называется синхронной, разве это не должно привести к тому, что NodeJS зависнет навсегда? - person CodeManX; 09.05.2014
comment
@CoDEmanX Ваша функция возвращается. Однако он возвращается немедленно, задолго до завершения запроса. Если вы хотите знать, когда эти данные будут готовы, вам нужно использовать callback, и из-за этого я не думаю, что библиотека sync много для вас делает. node.js спроектирован так, чтобы быть очень асинхронным, и это здорово! С таким языком, как PHP, у вас есть определенное количество процессов, скажем, 20, и если все они ожидают ожидания какого-то медленного запроса, то другие приложения не могут даже загружать простые страницы. - person Paul; 09.05.2014
comment
@CoDEmanX При наличии только одного процесса и потока в node.js все 20 запросов могут выполняться, но ваш сервер не блокируется, поэтому он может одновременно обслуживать запросы другим пользователям. Это довольно круто. - person Paul; 09.05.2014
comment
@CoDEmanX Если вы собираетесь использовать много node.js, я бы посоветовал вам избегать библиотеки sync и изучать асинхронный способ работы. Прочтите о event loop в Javascript, а затем о том, как работают промисы, и взгляните на библиотеку bluebird промисов. Это действительно приятно! - person Paul; 09.05.2014
comment
Спасибо за ваши рекомендации, я проверю bluebird. Я определенно должен использовать асинхронность, и я это сделаю, как только позволит время. Но для моего текущего проекта я мог бы даже запускать свой скрипт только на стороне клиента (= в браузере). Это не должно быть слишком плохо, так как мой набор данных и близко не подходит к большим данным, и в любом случае это автономная задача. - person CodeManX; 09.05.2014