使用wrapAsync进行同步调用

时间:2015-07-25 15:17:07

标签: javascript meteor

我写了一段代码来从文件中获取CSS内容,我想在我的帮助函数中获取这些数据。

服务器端:

Meteor.methods({

    'getCSS': function(filename) {
        return '<style>' + Assets.getText('css/' + filename) + '</style>';
    }

});

css文件夹位于private文件夹内,包含多个页面所需的CSS文件。据我所知,服务器端代码可以正常工作。

客户端:

Template.home.helpers({

    'css': function() {

        var asyncFn = function(fn, cb) {
            Meteor.call('getCSS', fn, function(err, res) {
                console.log(res);   // prints data correctly
                cb && cb(null, res);
            });
        }
        var syncFn = Meteor.wrapAsync(asyncFn);
        var result = syncFn('home.css');
        console.log(result);    // undefined
        return result;

    }

});

在研究了如何使用Meteor.wrapAsync之后,这是我能提出的最佳解决方案。不确定我错过了什么。我按照this博客的说明进行了操作。

3 个答案:

答案 0 :(得分:2)

您不能在客户端上使用Meteor.wrapAsync,因为在服务器上,同步性的幻觉取决于Fibers,并且客户端上没有这样的并行。

Fibers有效地内联异步函数,以便在等待回调时可以运行其他代码。除此之外,它还有助于消除callback pyramid of doom反模式。但是,它确实使得你的代码更难以推理,因为如果Javascript对象在光纤之间共享,你必须明确考虑你的代码何时可能会产生(自愿预先占用,例如通过进行数据库调用)。

在任何情况下,在客户端上出现类似内容之前可能还需要一段时间 - 正如您所看到的,Fibers是作为节点的C ++包实现的,并且不能简单地使用Javascript完成,因为它实际上是异步函数调用看起来是同步的。

在你的情况下,延迟加载CSS的正确方法(而不是将其包含在Meteor包的其余部分中)只是将它放在public/文件夹中(或包含在包中)使用{isAsset: true})并在需要时使用<head>标记加载。

答案 1 :(得分:0)

我并不完全明白你在这里想要达到的目标。

从我的角度来看,cas应该从第一次加载加载和编译。不要认为加载CSS是个好主意...你将无法卸载。

如果您在跟踪器计算中(例如,在路由器中,例如在渲染事件上),您可以使用ReactiveMethod包来进行同步调用。它使用跟踪器依赖性来等待响应。

另外,您最终可以设置服务器端路由从私人文件夹中提供CSS文件...

如果您需要,

干杯

答案 2 :(得分:0)

我没有将返回值存储在局部变量中,而是使用了Session。现在它有效!

Template.home.helpers({

    'css': function() {

        Meteor.call('getCSS', 'home.css', function(err, res) {
            Session.set('css', res);
        });
        return Session.get('css');

    }

});