Будущее.wait() не может ждать без волокна (в ожидании другого будущего в Meteor.метод)


В Meteor я пишу метод, который должен будет проверять подкаталоги определенного пути для новых файлов. Сначала я хотел бы просто перечислить подкаталоги в Meteor, после чего я child_process.exec простой скрипт bash, который перечисляет файлы, добавленные с момента последнего выполнения.

У меня возникли некоторые проблемы с тем, чтобы обнаружение каталогов было асинхронным (Error: Can't wait without a fiber). Я написал синхронную версию, но наличие обоих fs.readdir и fs.stat вместо их синхронных альтернатив позволяет мне поймать ошибки.

Вот код:

function listDirs(dir, isDir){

    var future1 = new Future();fs.readdir(dir, function(err, files){

            if (err)
                throw new Meteor.error(500, "Error listing files", err);

            var dirs = _.map(files, function(file){

                var future2 = new Future();
                var resolve2 = future2.resolver();

                fs.stat(dir+file, function(err, stats){

                    if (err)
                        throw new Meteor.error(500, "Error statting files", err);

                    if (stats.isDirectory() == isDir && file.charAt(0) !== '.')
                        resolve2(err, file);

                });

                return future2;

            });

            Future.wait(dirs);

            //var result = _.invoke(dirs, 'get');

            future1['return'](_.compact(dirs));
        });

        return future1.wait();
    }

Ошибка Error: Can't wait without a fiber связана с future2. Когда я комментирую Future.wait(dirs), сервер больше не падает, но это примерно то, что я сделал, пытаясь решить эту проблему. : /

Другая функция _.map, которую я использую в другой части метода, прекрасно работает с фьючерсами. (см. также https://gist.github.com/possibilities/3443021 где я нашел свое вдохновение)

1 7

1 ответ:

Оберните обратный вызов в Meteor.bindEnvironment, Пример:

fs.readdir(dir, Meteor.bindEnvironment(function (err, res) {
    if (err) future.throw(err);
    future.return(res);
}, function (err) { console.log("couldn't wrap the callback"); });

Meteor.bindEnvironment делает много вещей, и одна из них заключается в том, чтобы убедиться, что обратный вызов работает в волокне.

Еще одна вещь, которая может быть полезной, - это var funcSync = Meteor._wrapAsync(func), которая использует фьючерсы и позволяет использовать вызов функции в синхронном стиле (но это все еще асинхронно).

Смотрите эти видео на evented mind, если хотите узнать больше: https://www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables https://www.eventedmind.com/posts/meteor-what-is-meteor-bindenvironment