Может ли кто-нибудь объяснить, как работает 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]