Может ли кто-нибудь объяснить, как работает Meteor.defer()?

Итак... Meteor.defer(function(){ // stuff }) не находится в документах:

https://github.com/meteor/meteor/issues/2176

Но эти ссылки, похоже, говорят, что это просто эквивалентно

Meteor.setTimeout(function(){ // stuff }, 0);

Если это так, как это сделать, гм, что-нибудь? Это в основном говорит: "Подождите 0 мс, а затем запустите функцию".

Итак... он мгновенно запускает функцию.

Что мне здесь не хватает? Это похоже на Tracker.afterFlush или что-то в этом роде? Как-то дожидаться "вещей" (каких вещей?) До завершения?

Ответ 1

Я вижу Meteor.defer() много на SO, который используется как часть взлома для дополнительных вспомогательных методов для запуска после того, как dom (несколько) загружен - в основном, чтобы получить тот же эффект, что и исполняемый код внутри Template.foo.rendered метод.

Однако основным (и лучшим) использованием Meteor.defer является выполнение задачи асинхронно.

Скажем, у нас есть приложение, в котором мы отправляем электронное письмо. На сервере может потребоваться несколько секунд для обработки внутри метеорного метода, что резко замедлит ваше приложение. Однако, если вы завершите этот процесс в Meteor.defer, обработка электронной почты не будет блокировать выполнение, сообщение по-прежнему отправляется (когда оно получает шанс, а не мгновенно), но все выполняется намного быстрее, поскольку следующий код не ждет. Существует отличный пример, посвященный отсрочке исполнения в Bulletproof Meteor.

Фактически вы можете получить тот же эффект с помощью setTimeout(f,0) - если у вас медленная функция, вы можете обернуть его в setTimeout, а остальная часть кода будет завершена, и "отложить" медленный процесс в тайм-аут, поэтому, хотя это не похоже на то, setTimeout(f,0) действительно имеет довольно полезную цель!

Чтобы увидеть пример этого в действии, здесь скрипка, откройте консоль и посмотрите, где находятся журналы "foo".

Ответ 2

Я столкнулся с некоторыми проблемами в своем проекте из-за асинхронного обратного вызова. Внутри onCreated я делал сервер Meteor.call и задавал ответ внутри реактивногоVar. И я делал что-то внутри onRendered с этим реактивнымVar. Каждый раз, когда Реактивный Var показывался undefined.

Итак, я использовал Meteor.defer(function(){...}) внутри onRendered, и он переместил мою проблему.

Вот несколько примеров с использованием и без использования Meteor.defer()

Template.myTemplate.onCreated(function () {
    var instance = this;
    instance.myTemplateModel = new ReactiveDict();

    Meteor.call('all-user', function(err, res){
        if(res){
            console.log('inside callback');
            instance.myTemplateModel.set('users', res);
        }
    });
});

Template.myTemplate.onRendered(function () {
    var instance = this
    console.log('rendered start');
    Meteor.defer(function(){
         console.log(instance.myTemplateModel.get('users'));
    });
    console.log('render end');
});

Консоль:

/*Without Meteor.defer()*/         |  /*With Meteor.defer()*/
render start                       |  inside callback
undefined                          |  render start
render end                         |  render end
inside callback                    |  [Object, Object, Object]