Подтвердить что ты не робот

Как ждать на http-вызовах в Iron Routers onBeforeAction?

Я хочу создать предварительную загрузку script, которая выполняет несколько асинхронных функций для загрузки внешнего контента. Я довольно близко здесь, но я не совсем понял, как отложить вызов this.next() в моей функции onBeforeAction. В приведенном ниже коде вы можете видеть, что я использую цикл и setTimeout, но я каким-то образом теряю контекст моего маршрутизатора, а this.next() - undefined. Я считаю, что это связано с тем, что моя функция preloadProject заканчивается, и маршрутизатор предупреждает меня, что я забыл вызвать this.next(); до завершения моей функции waitToRender.

if (Meteor.isClient) {
    IR_BeforeHooks = {
        preloadProject: function() {
            var itemsProcessed = 0;
            _.each(items.items, function(e) {
                    HTTP.get(e.S3URL, {
                            headers: {
                                'Accept': '*/*'
                            },
                            responseType: 'arraybuffer' //requires aldeed:http
                        }, function(error, result) {
                            if (error) {
                                Session.set('error', {
                                    'title': 'Could not download',
                                    'message': error
                                });
                            }
                            if (result) {
                                itemsProcessed = itemsProcessed + 1;
                            }
                        }) //http get
                }) //each
            function waitToRender(router) {
                console.log('waiting...')
                var progress = (itemsProcessed / items.items.length) * 100;
                if (progress < 100) {
                    $('.progress-bar').css('width', Math.floor(progress) + '%');
                    setTimeout((function() {
                        waitToRender(router);
                    }), 50);
                    //console.log('timeout for a few ms here')
                }
                else {
                    console.log('all done, render');
                    router.next(); // I get this is not a function error here
                }
            }
            waitToRender(this);
        }
    }
}

и мой маршрутизатор

Router.before(
    IR_BeforeHooks.preloadProject, 
    {
        only:['editor', 'viewer', 'embedder']
    }
);

Из-за сложных требований в моем проекте мне нужно выполнить эти задачи перед рендерингом. Как я могу заставить Iron Router ждать своих HTTP-вызовов, не блокируя браузер?

4b9b3361

Ответ 1

Я нашел решение. Проблема, как я подозревал, заключалась в том, что Iron Router обнулялся, когда моя основная функция перехвата завершила синхронизацию. Поэтому, чтобы исправить это, я настраиваю свою собственную копию this.next, когда я начинаю свою работу, и вызываю мою копию функции, когда моя работа async завершена.

IR_BeforeHooks = {
  preloadProject: function() {
    var myNext = this.next;
    ...//http calls and etc
    function waitToRender(router) {
      console.log('waiting...')
      var progress = (itemsProcessed / items.items.length) * 100;
      if (progress < 100) {
        ...//use set timeout to recall waitToRender
      }
      else{
        myNext();
      }
    }
  }
}

Ответ 2

Поместите router.next() вне else блока, даже если вы ничего не визуализируете, вам нужно позвонить next.

 if (progress < 100) {
                        $('.progress-bar').css('width', Math.floor(progress) + '%');
                        setTimeout((function() {
                            waitToRender(router);
                        }), 50);
                        //console.log('timeout for a few ms here')
                    }
                    else {
                        console.log('all done, render');
                    }
router.next();