【问题标题】:JSONP using ContentService of Google Apps Script?JSONP 使用 Google Apps 脚本的 ContentService?
【发布时间】:2012-12-26 13:15:24
【问题描述】:

我正在尝试使用ContentService,在带有Google Apps Script 的网页中提供JSONP,遵循“在网页中提供 JSONP” 子下this link 中提供的示例-topic.

GS 代码:

function doGet(request) {
  var events = CalendarApp.getEvents(
    new Date(Number(request.parameters.start) * 1000),
    new Date(Number(request.parameters.end) * 1000));
  var result = {
    available: events.length == 0
  };
  return ContentService.createTextOutput(
    request.parameters.prefix + '(' + JSON.stringify(result) + ')')
    .setMimeType(ContentService.MimeType.JSON);
}

HTML/JS 代码:

<script src="https://script.google.com/macros/s/AKfycbwZCY0qrZ09szGvKOttA30IaJkdMAZrh_oNnvv0qzCqFWyuO5Wc/exec?start=1325437200&end=1325439000&prefix=alert"></script>


我通过将 GS 代码部署为 webapp 并使用以下参数发布了它:

  • 执行应用程序为:用户访问网络应用程序
  • 有权访问应用的人:任何人

不幸的是,每当我尝试运行/打开包含代码的 HTML 文件时,我在浏览器的控制台中收到以下错误,但什么也没发生:

如何正确运行 Google Apps 脚本链接中提供的这个示例?




[可选] 详细调查问题:

在浏览器生成的资源文件中发现的错误如下:

而浏览器翻译的DOM如下:

<html>
   <head>
       <script src="https://script.google.com/macros/s/AKfycbwZCY0qrZ09szGvKOttA30IaJkdMAZrh_oNnvv0qzCqFWyuO5Wc/exec?start=1325437200&amp;end=1325439000&amp;prefix=alert">
       </script>
   </head>
   <body></body>
</html>

生成的链接,在我的例子中是:
"https://script.google.com/macros/s/AKfycbwZCY0qrZ09szGvKOttA30IaJkdMAZrh_oNnvv0qzCqFWyuO5Wc/exec?start=1325437200&end=1325439000&prefix=alert"

如果此链接放置在浏览器地址栏中,则会显示以下消息:

这意味着返回的授权响应无法在浏览器上显示并被翻译为有效的 DOM。

如何解决这个问题?

【问题讨论】:

    标签: javascript google-apps-script jsonp


    【解决方案1】:

    JSONP 需要以下任何一项才能工作:

    1. 匿名访问,在“用户访问 webapp”模式下不可用 - 您需要以“像我一样执行”运行它。
    2. 不使用任何需要授权的服务的脚本,在这种情况下,您可以选择“用户访问 webapp”。这仅适用于登录到 Google 的用户,与以前的模式相比,使用它的唯一优势是所用服务的任何配额都将应用于每个用户,而不是应用于 webapp 的所有用户。一般来说,更喜欢选项 1。
    3. 已被用户预授权的脚本。这也仅适用于登录用户,但它可以让您使用任何服务。请参阅下文了解如何使用它。

    我假设您正在尝试使用 3 - 否则,请使用 1,它会正常工作。如果您确实需要 3 个(例如,访问用户电子邮件的 JSONP 服务),您将必须让他们能够在服务运行之前对其进行授权。为此,请在 doGet() 中添加类似这样的内容:

    function doGet(e) {
      if (e.parameter.auth) 
        return HtmlService.createHtmlOutput('Thank you! Now the script can run!');
      // ... rest of your code
    }
    

    然后,您可以向用户提供他们可以访问的 script.google.com/YOUR_SCRIPT_URL?auth=1 的链接。 (值 1 无关紧要......任何值都可以)。他们将获得授权页面,如果他们接受授权,他们将看到您的感谢消息,并且 JSONP 服务将为他们工作。只需执行一次...脚本将在用户下次访问您的页面时记住授权,除非您已将其更改为需要新权限或用户已撤销授权。

    【讨论】:

      【解决方案2】:

      问题是您尝试在客户端代码中执行的 jsonp“脚本”不是有效的 Javascript,如您所示,它是授权 html 网页。授权后应该没问题。不过,正如教程所说,在部署网络应用程序时,您可以以自己(“我”)的身份执行该应用程序,然后允许访问“任何人,甚至匿名”,并且您不会收到任何授权提示。虽然这显然有一些不同的行为,但在查看您的日历与用户的日历方面。 Corey G 提供了一种很好的方式来提示授权。

      【讨论】:

      • 以“我”身份执行应用程序,然后允许访问“任何人,甚至匿名”都不会得到任何授权提示,但谷歌给出的代码也不起作用。在拥有someone reported the issue 之后,Google 将其示例代码从ContentService.MimeType.JSON 更改为ContentService.MimeType.JAVASCRIPT,但它们都不起作用。
      • jQuery 回调方法suggested by Phil 也不再起作用。我怀疑谷歌仍然允许在 GAS 中这样做。
      【解决方案3】:

      在任何网页中提供 JSONP 总是会引发错误:

      Uncaught SyntaxError: Unexpected identifier

      这可能会得到纠正,但在意料之中,因为它正在将数据发送到外部页面,在 GAS 环境(UiApp 或 HTMLservice)之外。如果您在客户端创建自己的 javascript 函数,ServiceContent 运行良好..

      Apps 脚本代码:

      function doGet(e) {
         // ..more code
         lReturn = true;
         var mymessage = (lReturn==true) ? "your contact details are saved ! ":" data no saved.. ";
         var result = { status: lReturn, message : mymessage };
         return ContentService.createTextOutput(
           e.parameter.prefix + '(' + JSON.stringify(result) + ')')
          .setMimeType(ContentService.MimeType.JSON);`
        }
      

      和 Javascript 代码(使用 JQuery):

      var url = <your Apps Script URL>?prefix=myabc
      $.ajax({
        type: "GET",
        url: url1,
        data: {callback:"?"},
        dataType: "script"
        }).done( function( data ) {
               console.log(data); //data returned : UNDEFINED
      });
      

      还有你自己的javascript函数:

      function myabc(data) {
        //alert(data);
        //alert(data.message);
        //var xyz = JSON.stringify(data);
        //alert(xyz);
        alert(data.message);
      }
      

      最好的问候
      @Mlaynes http://mlaynessanchez.blogspot.com

      【讨论】:

        【解决方案4】:

        对于 ajax 调用,您必须在服务器端使用 setMimeType (ContentService.MimeType.JAVASCRIPT);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-07-02
          • 1970-01-01
          • 2012-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多