如何在 Google Apps 脚本中使用 AngularJS 与服务器通信

How to communicate with server using AngularJS within Google Apps Script

最近可以通过 iframe 沙盒模式在 google 应用程序脚本中使用 angularjs。

我的问题是在尝试与服务器(gapps 电子表格)通信并在 return 中接收异步数据时出现的。

从服务器接收数据的实现是使用带有回调函数的函数,如下所示:

google.script.run.withSuccessHandler(dataGatheringFunction).getServerData();

getServerData() 将是一个驻留在服务器端的函数,它会 return 一些数据,通常来自随附的电子表格。我的问题是如何在AngularJS的参数内使用回调函数。典型的 $http 函数可以放在提供程序中,范围值可以在 then.() return 之后填充。我还可以调用 $q。但是我该如何处理google回调的必要性呢?

这是我目前正在处理的内容的简化版本:

app.factory("myFactory", function($q){

  function ssData(){
  var TssData = function(z){
  return z;
}
google.script.run.withSuccessHandler(TssData).getServerData();
var deferred = $q.defer();
var d = deferred.resolve(TssData)
console.log("DP: " + deferred.promise);
return deferred.promise;
}  
return ssData();
})

然后在控制器中解析类似于这样的服务器调用: myFactory.then(在这里用return数据设置一些变量)

我的问题很简单 - 如何处理提供程序中的回调函数?

脚本没有抛出任何错误,但没有 return 来自服务器的数据。我可以使用旧的 $timeout 技巧来检索数据,但应该有更好的方法。

我的解决方案是一起摆脱 $q, promise 场景。我使用 $rootScope.$broadcast 从服务器更新作用域变量。

Link to spreadsheet with script.

This guy 似乎很高兴地将数据从 GSheet 中提取到 angular 中,而无需做任何花哨的事情。

function gotData(res) {
  $scope.validUser = res.validUser;
  var data = angular.copy(res.data), obj, i=0;
  Object.keys(data).forEach(function(sh) {
    obj = {title: sh, checked: {}, showFilters: false, search: {}, sort: {index: 0, reverse: false}, currentPage: 0, checkedAll: true, showBtns: true, searchAll: ''};
    obj.heading = data[sh].shift();
    obj.list = data[sh];
    obj.heading.forEach(function(s,i) {
      obj.checked[i] = true;
    });
    $scope.sheets.push(obj);
  });
  $scope.sheets.sort(function(a,b) {
    return a.title > b.title ? 1 : -1;
  });
  $scope.gotData = true;
  $scope.$apply();
}
google.script.run.withSuccessHandler(gotData).withFailureHandler($scope.gotError).getData();

您只需要$应用服务器函数的输出:

google.script.run.withSuccessHandler(function(data) {

  $scope.$apply(function () {
    $scope.data = data;
  });

}).withFailureHandler(errorHandler).serverFunction();

也许确保 google.script.run 回调在 Angular JS 摘要循环中自动注册的最优雅的解决方案是使用 $q 构造函数来承诺 google 回调。因此,使用上面的示例:

app.factory('myFactory', ['$q', function ($q){

  return {ssData: ssData};

  function ssData(){
    var TssData = function(z){
      return z;
    };

    var NoData = function(error) {
      // Error Handling Here
    };

    return $q(function(resolve, reject) {
      google.script.run
        .withSuccessHandler(resolve)
        .withFailureHandler(reject)
        .getServerData();
    }).then(TssData).catch(NoData);
  }

}]);

然后在你的控制器中你可以调用myFactory.ssData()

因为我不知道 TssData 到底在做什么,所以我把它包含在这里,但请注意,这只是 returns 在此上下文中的另一个承诺,您仍然需要在控制器中处理它:

myFactory.ssData().then(function(response) {
  // Set data to the scope or whatever you want
});

或者,如果 TssData 正在进行某种数据转换,您可以通过将其添加到工厂函数来公开它。如果它真的只是返回响应,您可以重构代码并省略 TssDataNoData 并完全在控制器中处理承诺:

app.factory('myFactory', ['$q', function ($q){

  return {ssData: ssData};

  function ssData(){
    return $q(function(resolve, reject) {
        google.script.run
          .withSuccessHandler(resolve)
          .withFailureHandler(reject)
          .getServerData();
    });
  }
}]);

app.controller('myController', ['myFactory', function(myFactory) {
  var vm = this;
  myFactory.ssData()
    .then(function(response) {
      vm.myData = response;
    }).catch(function(error) {
      // Handle Any Errors
    });
}]);

这里有一篇关于承诺的优秀文章(在 Angular 和其他地方):http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html