【问题标题】:How to understand asynchronous Meteor.call on the client side如何理解客户端的异步 Meteor.call
【发布时间】:2016-06-17 05:32:30
【问题描述】:

我正在做一个 Meteor 项目,想在客户端的模板助手中获取 Meteor.call 的返回值。一开始,我只是在回调函数中设置一个变量,然后在Meteor.call 之外获取变量的值。我发现Meteor.call 之后的代码根本不执行。然后我搜索了一下并使用了Session,它可以工作。但我真的不明白其中的原因。这是我的原始代码和修改后的代码。谁能为我解释一下?谢谢!!

原错误代码:html

 <div id="text-result-main">
   <h2>{{title}}</h2>
 </div>

js

Template.texts.helpers({
  title: function(){
    var index = Router.current().params.index;
    Meteor.call('getTitle', index,function(error, result){ 
       titles = result;
    });
    console.log(titles);
    return titles;
 }});

集合 text.js

Text = new Mongo.Collection("text");
Meteor.methods({
  'getTitle': function(myindex){
     return Text.findOne({index: myindex}).title;
  }});

工作代码:js

Template.texts.helpers({
 title: function(){
      var index = Router.current().params.index;
      Meteor.call('getTitle', index,function(error, result){ 
        Session.set("titles",result);
      });
      console.log(Session.get("titles"));
     return Session.get("titles"); 
}});

请注意,我根本没有向客户端发布集合文本,因为它实在是太大了。每次运行错误代码刷新页面时,都看不到“title”的内容,或者在控制台上看不到。但是当我设置会话时,它可以工作。我真的不明白它是如何在这里工作的。谢谢

【问题讨论】:

  • 如果您在异步调用时遇到问题(我可以告诉您),只需将您的 Meteor.call 转换为同步调用即可。

标签: javascript asynchronous meteor


【解决方案1】:

异步性反应性

有两个问题

这种做作

Meteor.call('getTitle', index,function(error, result){ 
   titles = result;
});

在流星调用内部以异步方式执行。所以你的助手的 return 被立即调用,并返回一个空值。

在浏览器的控制台中试一试。

但是,当您使用会话变量时,为什么您的模板使用 {{title}} 正确呈现? 这是因为 Session 是一个响应式数据源,这意味着对它的每次更改都会触发涉及该数据的所有模板的重新计算。

这是一个时间表:

  • 方法被调用

  • 返回空值

  • 方法执行,设置变量值

  • 如果变量是响应式数据源,则重新计算模板。 (在您的情况下,会话是一个反应式数据源。)

走得更远

在这种情况下,我会使用响应式 var,它与会话变量非常接近,但范围仅限于模板。

反应式数据源的好读物:http://richsilv.github.io/meteor/meteor-reactive-data-types/

【讨论】:

    【解决方案2】:

    问题在于Meteor.call() 在与回调配对时是异步的。

    所以当title() 开始执行时,它不会等待您的Meteor.call() 调用返回结果(或者可能是错误)。它继续执行。这称为异步执行。

    简而言之,您正在尝试记录 titles 中不存在的键 Session 的值(因为此时您的异步 Meteor 调用的状态是未知的)。

    尝试将控制台日志语句移动到与您的Meteor.call() 配对的回调中,一旦在Session 中成功设置,您就可以看到结果。


    解决您的问题的方法是让您的 Meteor.call() 像这样同步:

    Template.texts.helpers({
     title: function(){
          var index = Router.current().params.index;
          var result = Meteor.call('getTitle', index); // <--- this is synchronous code now
          Session.set("titles",result);
          console.log(Session.get("titles"));
          return Session.get("titles"); 
    }});
    

    删除回调使Meteor.call() 同步运行。

    如果没有在服务器上传递回调,则方法调用 将阻塞直到方法完成。它最终会返回 方法的返回值,否则会抛出异常 方法抛出异常。

    (来自http://docs.meteor.com/api/methods.html#Meteor-call

    【讨论】:

    • 嗨!这实际上在我的代码中不起作用。我只能使用异步调用并在其中设置会话。
    • 您的代码 sn-ps 另有建议。 Meteor IIRC 中允许客户端会话 setsgets
    【解决方案3】:

    为什么不使用这样的东西:

    title: function(){
        var index = Router.current().params.index;
        var a = Text.findOne({index: myindex}).title;
        console.log(a);
        return a;
    

    没有方法

    【讨论】:

    • 确实,没有更多信息,方法调用在这里不是强制性的。
    • 因为我的收藏太庞大了,如果我把它们发布给客户端,性能将无法忍受。还是谢谢你的建议
    • 尝试在 mongodb 上使用部分索引。部分索引只索引集合中满足指定过滤器表达式的文档。所以你将只发布集合的子集。
    猜你喜欢
    • 2015-10-18
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多