繁体   English   中英

在 Google Apps 脚本中从服务器到客户端进行通信

[英]Communicate from server to client side in Google Apps script

我正在尝试编写一个包含客户端和服务器端组件的 Google Apps 脚本。 客户端组件显示一个进度条。 客户端调用服务器端函数(异步调用),其进度必须显示在客户端进度条中。 现在,我想要的是能够根据来自服务器端功能的反馈更新客户端进度条。 这可能吗?

由于 JS 使服务器端调用异步,因此我无法在客户端调用函数并更新进度条,从而真正实现循环。

我当然可以将服务器端函数的执行拆分成多个步骤,从客户端一个一个调用,每次更新状态栏。 但我想知道是否有更好的解决方案。 有没有办法从服务器端调用客户端函数,并根据传递的参数更新进度条? 或者有没有办法从服务器端访问客户端进度条对象并修改它?

我处理这个问题的方式是让一个中间人(现在向 Romain Vialard 提出这个想法)处理进度: Firebase

HTML/客户端可以连接到您的 Firebase 帐户(它们是免费的!)并“观察”更改。

客户端代码可以在执行代码时更新数据库 - 这些更改会立即通过 Firebase 反馈到 HTML 页面。 有了它,您可以更新进度条。

罗曼在这里有一个小例子/描述

我使用的代码:

//Connect to firebase
var fb = new Firebase("https://YOUR_DATABASE.firebaseio.com/");
//Grab the 'child' holding the progress info
var ref = fb.child('Progress');
//When the value changes
ref.on("value", function(data) {
  if (data.val()) {
    var perc = data.val() * 100;
    document.getElementById("load").innerHTML = "<div class='determinate' style='width:" + perc + "%\'></div>";
  }
});

在客户端,我使用Firebase 库来更新进度:

var fb = FirebaseApp.getDatabaseByUrl("https://YOUR_DATABASE..firebaseio.com/");
var data = { "Progress": .25};
fb.updateData("/",data);

与其将工作请求和进度更新联系在一起,我建议您将这两个关注点分开。

在服务器端,应客户端请求执行工作的函数应该更新状态存储; 例如,这可能是一个 ScriptProperty。 工作职能在完成工作之前不需要响应客户。 服务器还应该有一个函数,可以被客户端调用来简单地报告当前的进度。

当客户端第一次调用服务器请求工作时,它也应该调用进度报告器。 (大概,第一次调用将获得0%的结果。)状态调用的onSuccess处理程序可以更新您用来表示进度的任何视觉效果,然后再次调用服务器的进度报告器,将其自身作为成功处理程序。 当然,这应该延迟完成。

当进度达到100%或工作完成时,可以关闭客户端的进度检查器。

基于 Jens 的方法,您可以使用CacheService作为数据代理,而不是外部服务。 我处理这个问题的方法是让我的“服务器”应用程序生成一个临时缓存键,它会返回到“客户端”应用程序的成功回调。 然后,客户端应用程序每隔一段时间轮询这个缓存键,以查看服务器应用程序是否已将结果返回到缓存中。

服务器应用程序返回一个临时缓存键并包含一些帮助函数来简化客户端的检查:

function someAsynchronousOperation() {
  var interimCacheKey = createInterimCacheKey();

  doSomethingComplicated(function(result) {
      setCacheKey(interimCacheKey, result);
  });

  return interimCacheKey;
}

function createInterimCacheKey() {
  return Utilities.getUuid();
}

function getCacheKey(cacheKey, returnEmpty) {
  var cache = CacheService.getUserCache();
  var result = cache.get(cacheKey);

  if(result !== null || returnEmpty) {
    return result;
  }
}

function setCacheKey(cacheKey, value) {
  var cache = CacheService.getUserCache();

  return cache.put(cacheKey, value);
}

请注意,默认情况下 getCacheKey 不会返回。 这是为了在缓存条目返回非空值之前不会调用 google.script.run 的 successHandler。

在客户端应用程序中(我在其中使用 Angular),您调用服务器中的异步操作,并等待其结果:

google.script.run.withSuccessHandler(function(interimCacheKey) {
  var interimCacheCheck = $interval(function() {
    google.script.run.withSuccessHandler(function(result) {
      $interval.cancel(interimCacheCheck);
      handleSomeAsynchronousOperation(result);
    }).getCacheKey(interimCacheKey, false);
  }, 1000, 600); // Check result once per second for 10 minutes
}).someAsynchronousOperation();

使用这种方法,您还可以报告进度,并且只有在进度达到 100% 后才取消您的支票。 在这种情况下,您希望消除间隔到期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM