【问题标题】:Google Apps Script: passing error into templated HTMLGoogle Apps 脚本:模板 HTML 中的解析错误
【发布时间】:2019-05-24 00:48:42
【问题描述】:

我有以下代码:

code.gs:

function onOpen() {
    var ui = SpreadsheetApp.getUi();
    ui.createMenu('My Menu')
      .addItem('Test', 'showTestForm')
      .addToUi();
}

function showTestForm() {
    var html = HtmlService.createHtmlOutputFromFile('TestForm');
    SpreadsheetApp.getUi().showModalDialog(html, 'TEST');
}

function Test(formObject){
  Logger.log("TEST")
  var a = new Error( "Allready present "+ formObject);
  a.error_code = 99;
  Logger.log(JSON.stringify(a));
  throw a;
}

TestForm.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8" />
    <base target="_top">
    <script>
        function onFailure(error) {   
            var keys = Object.keys(error);
            alert(JSON.stringify(keys));
            alert(JSON.stringify(error.message));
            alert(JSON.stringify(error.error_code));
        }

        function onSuccess() {
            alert("Success");
        }
    </script>
</head>
<body>
    <input type="submit" value="Save" onclick="google.script.run.withFailureHandler(onFailure).withSuccessHandler(onSuccess).Test('1')" />
    <input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>

当我从菜单中打开 TestForm 并按“保存”时,我从 Logger 得到以下日志:

[18-12-24 23:08:24:765 PST] TEST
[18-12-24 23:08:24:766 PST] {"message":"Allready present 1","error_code":99}

所以我明白了,那个错误对象有属性'message'和'error_code'。但在浏览器中,我收到了以下警报:

["name"]
"Error: Allready present 1"
undefined

所以我明白了,接收到的错误对象只有一个空的(我已经检查过)属性“名称”。但是,如果我只是引用属性“消息,我在原始对象中得到了字符串(但不一样)。看起来那个对象没有“错误代码”。 怎么了?

【问题讨论】:

  • error.name 显示什么?也可以试试alert(JSON.stringify(error['error_code']));
  • @TheMaster:分别为""undefined
  • 尝试像在 a = {message: message, statusCode: statusCode} 中那样传递常规对象字面量,而不是调用 Error 构造函数
  • 错误对象是标准的内置对象。您不能只为其添加属性。只有名称和消息是有效的属性。但是您可以在消息中包含一个对象。 var a = new Error( JSON.stringify({msg:"Allready present "+ formObject,code:99}));
  • 解析它。 JSON.parse(error.message).msgJSON.parse(error.message).Error.msg

标签: javascript forms google-apps-script web-applications


【解决方案1】:

我想你可能会喜欢一个完整的工作示例,因为我知道这些东西可能会让人非常沮丧。

这是一个简单的模板化 HTML 文件示例,可用作对话框或 web 应用程序。它所做的只是在每个页面的页眉和页脚中创建一个带有今天日期的 Google Doc 文件,并将该文件放入与包含脚本的电子表格相同的目录中。而已。我使用 Chrome 浏览器。我什至不在乎我的脚本是否不能在其他浏览器上运行。

这是 HTML:(文件名:'docwithdate.html')

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= include('resources') ?>
    <?!= include('css') ?>
  </head>
  <body>
    <?!= include('form') ?>
    <?!= include('script') ?>
  </body>
</html>

资源:(文件名:'resources.html')

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

CSS:(文件名:'css.html')

<style>
body {background-color:#ffffff;}
input[type="button"]{padding:0 0 2px 0;}
</style>

表单:(文件名:form.html)这可能是把模板的想法推得有点远。

<form id="myForm" onsubmit="event.preventDefault();processForm(this);" >
  <input type="text" id="txt1" name="filename" />
  <input id="btn" type="submit" value="Submit" />
</form>

Javascript:[文件名:'script.html')

<script>
    function createFile(){
      var name=document.getElementById('filename').value;
      google.script.run
      .withSuccessHandler(function(rObj){
        var html='<br /><a href="'+ rObj.url +'" onClick="google.script.host.close();">Go To File:' + rObj.filename + '</a>';
        $(html).appendTo("body");
      })
      .createTemplatedGoogleDoc(name);
    }

    function getInputObject(obj) {//I'm probably doing something wrong here. But this is what I had to do to get the object with the properties that I desired.  So if you have another way.  Go for it.
      var rObj={};
      for(var i=0;i<Object.keys(obj).length;i++){
        if(obj[i].type=="text"){
          rObj[obj[i].name]=obj[i].value;
        }
        console.log('Object.keys(rObj): %s',Object.keys(rObj).join(', '));
      }
      return rObj;
    }

    function processForm(obj){
      var fObj=getInputObject(obj);
      var name=fObj.filename;
      google.script.run
      .withSuccessHandler(function(rObj){
        document.getElementById("btn").disabled=true;
        var html='<br /><a href="'+ rObj.url +'" onClick="google.script.host.close();">Go To File:' + rObj.filename + '</a>';
        $(html).appendTo("body");
      })
      .createTemplatedGoogleDoc(name);
    }
    console.log('My Code');
</script>

Google 脚本:(文件名:Code.gs)

function onOpen(){
  SpreadsheetApp.getUi().createMenu('My Menu')
  .addItem("Open Templated Google Doc", 'showMyDialog')
  .addToUi()
}

function createTemplatedGoogleDoc(name){
  Logger.log(name);
  var doc=DocumentApp.create(name);//Creates a google doc
  var fldrs=DriveApp.getFileById(SpreadsheetApp.getActive().getId()).getParents();
  while(fldrs.hasNext()){
    var fldr=fldrs.next();
    if(fldr.getName()=="Create Templated Google Doc App"){
      var folder=fldr;
    }
  }
  Drive.Files.update({"parents": [{"id": folder.getId()}]}, doc.getId());//puts doc file into same directory as the spreadsheet that contains the script
  doc.addHeader().appendParagraph(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E MMM dd, yyyy"));
  doc.addFooter().appendParagraph(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E MMM dd, yyyy"));
  //doc.getBody().getChild(0).removeFromParent();
  doc.saveAndClose()
  var rObj={url:doc.getUrl(),filename:doc.getName()}
  return rObj;
}

function showMyDialog(){
  var ui=HtmlService.createTemplateFromFile('docwithdate').evaluate();
  SpreadsheetApp.getUi().showModelessDialog(ui, 'My Doc with Date');
}

function doGet(){//if you want a web app this is helpful
  return HtmlService.createTemplateFromFile('docwithdate').evaluate();
}

function include(filename){//this is the include that the template uses
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

这是一个非常简单的脚本。我希望它可以帮助您入门。

【讨论】:

  • 我的问题是关于传递一个错误对象,在你的例子中没有任何内容
  • 传递错误对象就像传递任何其他对象
  • 酷。但正如您在我的示例中看到的那样,它并没有起到怀疑的作用
  • 但是你的函数测试没有返回任何东西
  • 是的,但它会引发异常throw a;。我已经向用户显示了一个 HTMLOutput,他提交了一个表单,现在我应该返回一个错误
【解决方案2】:

按照@TheMaster的提议,有必要这样做:

代码.gs

function Test(formObject){
    var a = new Error( JSON.stringify({msg:"Allready present "+ formObject,code:99}));
    throw a;
}

TestForm.html

// removing "Error: " from message string to get our json back
var json = error.message.replace("Error: ",'')
var msg = JSON.parse(json).msg;
var code = JSON.parse(json).code;

也就是说,我们将json放入Error对象的属性message中,然后通过切割我们的json,进行解析,得到必要的值。

这并不完全是问题的答案,而是解决问题的好方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-09
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    相关资源
    最近更新 更多