【问题标题】:How to wait for meteor call response and then execute other statements in javascript?如何等待流星呼叫响应然后在javascript中执行其他语句?
【发布时间】:2018-08-29 16:41:40
【问题描述】:

我在流星的客户端事件中有两个流星调用,我想一个接一个地执行。但是当我调试时,流程并没有按照我想要的方式进行。

client.js

Meteor.call('methodCall',param1,param2,param3,function (error, result) {
    if (error) 
        console.log(error.reason);

    Session.set("xyz",result);
});

var abc=Session.get("xyz");

Meteor.call('methodCall',abc,param2,param3,function (error, result) {
    if (error) 
        console.log(error.reason);

    console.log("result: "+result);
    Session.set("cdf",result);
}); 

var pqr=Session.get("cdf");

如您所见,这是我要按顺序运行的代码,即一个接一个。但是当我调试代码时发现执行顺序是:

1. Meteor will be called
3. session.get("xyz") return undefined.
4. Meteor will be called
6. session.get("cdf") return undefined.
2. session.set() will have results as value.
5. session.get() will not have any value.

第二个meteor.call() 不会成功执行,因为第一个参数在第2 步之前执行的第3 步没有任何值。那么有什么方法可以实现这一点并等待流星调用完成以执行下一条指令?

【问题讨论】:

    标签: javascript node.js meteor angular-meteor


    【解决方案1】:

    其中一种方法是稍微重新组织您的代码。

    Meteor.call('methodCall',param1,param2,param3,function (error, result) 
    {
      if (error) console.log(error.reason);
      Session.set("xyz",result);
      var abc=Session.get("xyz");
      Meteor.call('methodCall',abc,param2,param3,function (error, result) 
      {
        if (error) console.log(error.reason);
        console.log("result: "+result);
        Session.set("cdf",result);
        var pqr=Session.get("cdf");
      });
    });
    

    【讨论】:

      【解决方案2】:

      我已经对这种情况的各种选择进行了一些研究,因为这里的其他人可能也已经面临过这种情况。

      选项 A - 客户端中的嵌套调用

      第一个也是最明显的一个是进行嵌套调用。这意味着在回调中收到结果后调用下一个函数。

      // level 1
      Meteor.call('methodCall', param1, param2, param3, function (error, result) {
          // level 2
          if (error) console.log(error.reason);
      
          Session.set("xyz",result);
      
          Meteor.call('methodCall',result, param2, param3, function (error, result) {
              // level 3...
              if (error) console.log(error.reason);
      
              console.log("result: "+result);
              Session.set("cdf",result);
          }); 
      
      });
      

      优点:经典的 js 方式,不需要花哨的新概念,服务器方法坚持简单的逻辑,而客户端则完成复杂的工作

      缺点:丑陋,会引起混乱,有时难以调试

      需要: Template.autorunTracker.autorun 以响应式捕获来自 Session 的更改。


      选项 B - 异步包装

      许多人可能已经发现此方法是将异步代码结构化为同步代码的第一选择。

      Fibers(以及使用 Fibers 的 wrapAsync)使代码仅看起来同步,但执行的性质保持异步。这与 Promises 的工作方式或 async/await 的工作方式相同。

      优点:在单一环境中功能强大

      缺点:不能与 Meteor.call 一起使用

      需要:要运行的光纤

      Meteor.call 的问题

      但是,您不能使用此功能轻松调用 Meteor 方法。考虑以下代码

      const param1 = "param1";
      const param2 = "param2";
      const param3 = "param3";
      
      
      const asyncCall = Meteor.wrapAsync(Meteor.call);
      const result1 = asyncCall("methodCall", param1, param2, param3);
      // result1 will be undefined
      

      为了进一步解释,我将引用documentation

      在客户端,如果你不传递回调并且你不在一个 存根,调用将返回未定义,您将无法获得 方法的返回值。那是因为客户端没有 光纤,所以实际上没有任何方法可以阻止遥控器 方法的执行。

      总结:Meteor.wrapAsync不能和Meteor.call一起使用。


      选项 C - 以一种方法捆绑

      除了尝试创建同步的流星调用序列,您还可以将所有参数和逻辑提供给单个服务器方法,该方法返回一个保留所有返回值的对象:

      client.js

      const param1 = "param1";
      const param2 = "param2";
      const param3 = "param3";
      
      
      Meteor.call('methodCall', param1, param2, param3, function (err, result) {
        const xyz = result.xyz;
        const cdf = result.cdf;
      });
      

      server.js

      function _methodCall(p1, p2, p3) {
        // ... 
        return result;
      }
      
      Meteor.methods({
        'methodCall'(p1, p2, p3) {
          const result1 = _methodCall(p1, p2, p3);
          const result2 = _methodCall(result1, p2, p3);
          return {
            xyz: result1,
            cdf: result2,
          }
        }
      })
      

      这将创建一个顺序执行(通过遵循您在问题中提供的顺序逻辑)并将其所有结果返回到一个捆绑对象中。

      优点:根据需要按顺序排列,一个请求 - 所有结果 缺点:要测试一个额外的方法,可以在方法之间引入紧密耦合,返回对象可能会变得很大且复杂,无法为客户端解析 要求:对方法设计有一定的了解

      如果我找到其他选项,我会将它们添加到这篇文章中。

      【讨论】:

        【解决方案3】:

        你必须使用promise,例如future fiber

        在服务器上

        Meteor.methods({
        'methodCall': function(params...){
          var future = new Future();
          try{
            your code...
            future.return(result)
          catch(e){
            future.throw(e)
          }finally{
            return future.wait();
          }
         },
        })
        

        在客户端

        Meteor.call('methodCall',params...,(err,res)=>{
          if(err){
           console.log(err);
          }else{
           console.log(res);
          }
        });
        

        参考链接https://github.com/jagi/meteor-astronomy/issues/562

        【讨论】:

          猜你喜欢
          • 2022-01-01
          • 2019-10-12
          • 1970-01-01
          • 1970-01-01
          • 2015-04-07
          • 2019-11-04
          • 1970-01-01
          • 2012-03-18
          • 1970-01-01
          相关资源
          最近更新 更多