簡體   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