【问题标题】:Meteor: long latency when returning from server metod callMeteor:从服务器方法调用返回时延迟很长
【发布时间】:2021-04-12 07:50:15
【问题描述】:

我做了一个 Meteor.call。我看到服务器执行它的代码并在不到一秒的时间内完成。然后,每隔一段时间,客户端就会等待很长时间才能收到响应。这发生在本地,因此与任何 Internet 连接问题无关。响应包含一个很小的对象,所以我也不认为这是 JSON 解析问题。

这里的重点是服务器已经完成并返回了它的响应......但客户端长达几分钟都没有收到它。

服务器代码:

findComments : function(ne, sw, filter, timezoneOffset) {
    // ... do some Mongo queries and updates ... etc.  nothing too weird.

    console.log("returning now...");
    return result;
}

客户端代码:

Meteor.call("findComments", ne, sw, filter, timezoneOffset, function(err, comments) {
    console.log("comments = " + comments);
    // ... and we're back
}

我可以在客户端代码的“Meteor.call”行和回调中设置断点。我在服务器上看到“现在返回......”,然后......什么也没有。我等了几分钟,然后我看到回调中返回给客户端的好结果。

这种行为可以在 Chrome 中看到,也可以在 Android 和 iOS 上已安装的应用中看到。它很少发生,但极具破坏性,我们无法隔离导致这种情况的任何特定条件。

怎么办??

编辑:

大约 2 分钟后,客户端最终会进入回调。在此期间,CPU 处于空闲状态。我还用一个简单的服务器调用对此进行了测试,该调用不带任何参数,并且在服务器上什么也不做......同样的效果。

所以,如果我在客户端停止执行以查看他在此期间在做什么,它会在此函数中停止,在 lib/trans-websocket.js 中:

var WebSocketTransport = SockJS.websocket = function(ri, trans_url) {                                             // 1263
    var that = this;                                                                                              // 1264
    var url = trans_url + '/websocket';                                                                           // 1265
    if (url.slice(0, 5) === 'https') {                                                                            // 1266
        url = 'wss' + url.slice(5);                                                                               // 1267
    } else {                                                                                                      // 1268
        url = 'ws' + url.slice(4);                                                                                // 1269
    }                                                                                                             // 1270
    that.ri = ri;                                                                                                 // 1271
    that.url = url;                                                                                               // 1272
    var Constructor = _window.WebSocket || _window.MozWebSocket;                                                  // 1273
                                                                                                                  // 1274
    that.ws = new Constructor(that.url);                                                                          // 1275
    that.ws.onmessage = function(e) {     <-- RIGHT HERE IS WHERE IT STOPS                                                                          // 1276
        that.ri._didMessage(e.data);                                                                              // 1277
    };                                                                                                            // 1278
    // Firefox has an interesting bug. If a websocket connection is                                               // 1279
    // created after onunload, it stays alive even when user                                                      // 1280
    // navigates away from the page. In such situation let's lie -                                                // 1281
    // let's not open the ws connection at all. See:                                                              // 1282
    // https://github.com/sockjs/sockjs-client/issues/28                                                          // 1283
    // https://bugzilla.mozilla.org/show_bug.cgi?id=696085                                                        // 1284
    that.unload_ref = utils.unload_add(function(){that.ws.close()});                                              // 1285
    that.ws.onclose = function() {                                                                                // 1286
        that.ri._didMessage(utils.closeFrame(1006, "WebSocket connection broken"));                               // 1287
    };                                                                                                            // 1288
};                                                                                                                // 1289

奇怪的是,我在这段代码中放置的任何断点都将被忽略。但我可以检查 MessageEvent e 的值:

bubbles    :    false
cancelBubble    :    false
cancelable    :    false
composed    :    false
currentTarget    :    WebSocket
data    :    "a["{\"msg\":\"updated\",\"methods\":[\"64\"]}"]"
defaultPrevented    :    false
eventPhase    :    2
isTrusted    :    true
lastEventId    :    ""
origin    :    "ws://localhost:3000"
path    :    Array[0]
ports    :    null
returnValue    :    true
source    :    null
srcElement    :    WebSocket
target    :    WebSocket
timeStamp    :    17400.095
type    :    "message"
__proto__    :    MessageEvent

【问题讨论】:

  • 这真的很奇怪。你能发布你的代码吗?
  • 当然可以,但也没什么。我现在将编辑问题。
  • 嘿@Marc 你有没有运气解决这个问题?
  • 能够通过使用 Meteor.apply 和 onResultReceived 选项来解决问题。详情请查看以下答案。

标签: meteor


【解决方案1】:

尝试像这样将你的函数放在 try/catch 中:

myFunction() {

      try {
             ...  
          } catch(e) {
              throw new Meteor.Error(e.code,e);
          }
}

然后在 Meteor.call 中捕获错误。可能是服务器出错了。

【讨论】:

  • 没有错误。就像我说的,服务器代码正常执行并在不到一秒的时间内返回结果。然后......客户端(有时,不可预测,很少)等待几分钟,然后进入回调。
【解决方案2】:

这适用于仍在寻找解决此问题的任何人。 正如 Meteor 文档中提到的那样。

一旦方法在服务器上完成运行,它会向客户端发送一条结果消息,其中包含在步骤 2 中生成的方法 ID 以及返回值本身。客户端存储这个供以后使用,但还没有调用方法回调。如果您将 onResultReceived 选项传递给 Meteor.apply,则会触发该回调。

参考:https://guide.meteor.com/methods.html#advanced-boilerplate

因此,如果您希望在服务器方法返回值后触发回调,那么您可以使用带有 onResultReceived 选项的 Metor.apply 方法。

Meteor.apply(
  "findComments",
  [ne, sw, filter, timezoneOffset],
  {
    onResultReceived: function(err, comments) {
      console.log("comments = " + comments);
      // ... and we're back
    }
  }

即使我也在为延迟时间而苦苦挣扎,但在超过它的瞬间之后。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-09
    相关资源
    最近更新 更多