【问题标题】:How to wait on http calls in Iron Router’s onBeforeAction?如何在 Iron Router 的 onBeforeAction 中等待 http 调用?
【发布时间】:2016-01-31 04:54:38
【问题描述】:

我想创建一个预加载脚本,该脚本执行许多异步功能来下载外部内容。我离这里很近,但我还没有完全弄清楚如何在我的 onBeforeAction 函数中推迟调用 this.next() 。在下面的代码中,您可以看到我使用了循环和 setTimeout,但是我以某种方式丢失了路由器的上下文,并且 this.next() 未定义。我相信这是因为我的 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 调用?

【问题讨论】:

    标签: javascript meteor iron-router


    【解决方案1】:

    我找到了解决方案。正如我所怀疑的,问题是当我的主要钩子函数完成同步工作时,Iron Router 正在使自己归零。因此,为了解决这个问题,我在开始工作时设置了自己的 this.next 副本,并在异步工作完成时调用该函数的副本。

    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(); 
    

    【讨论】:

    • 感谢您的回复,问题是在进度达到 100 之前我不想渲染。如果我将 router.next() 放在您推荐的位置,那么我最终会渲染waitToRender 的第一次迭代并一遍又一遍地调用 router.next 直到我的 http 调用完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    相关资源
    最近更新 更多