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

时间:2015-02-26 01:42:48

标签: angularjs google-apps-script

最近,通过iframe沙箱模式,可以在google apps脚本中使用angularjs。

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

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

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

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

这是我到目前为止所搞乱的简化版本:

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( 在这里设置一些带有返回数据的变量

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

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

4 个答案:

答案 0 :(得分:4)

您只需要 $ apply 来自服务器功能的输出:

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

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

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

答案 1 :(得分:4)

也许确保在AngularJS摘要周期中自动注册google.script.run回调的最优雅的解决方案是使用$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正在做什么,所以我将其包含在此处,但请注意,这只会在此上下文中返回另一个承诺,您仍需要在控制器中处理:

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

答案 2 :(得分:3)

This guy似乎将GSheet中的数据非常愉快地提取到角度,而不必做任何花哨的事情。

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();

答案 3 :(得分:2)

我的解决方案是一起摆脱$ q,promise方案。我使用$ rootScope。$ broadcast来更新服务器的范围变量。

Link to spreadsheet with script