我可以在循环中提高UrlFetchApp.fetch()的处理速度吗

时间:2019-03-05 12:15:33

标签: performance optimization google-apps-script google-apps urlfetch

2我有一个在线Web表单,我正在使用Google表格进行大量提交。

该代码对于几条记录工作正常,但是当我添加1000-2000条记录时,我看到处理时间确实很长,并且脚本运行和完成需要很长时间。最终超时。

我可以通过更新代码来提高速度吗?

当前,对于每个电子邮件地址,循环正在运行,我认为这是造成问题的原因。

这是我当前的代码:

     //sheet refers to the sheet that includes email list (email list includes "Email" as a column header
    //paramValueSheet refers to the sheet that includes parameters values

var SENT_TAG = 'SEND_CONFIRMED';
var sheet = SpreadsheetApp.getActive().getSheetByName('EmailAddressSheet');
var paramValueSheet = SpreadsheetApp.getActive().getSheetByName('ParameterValuesSheet');

    function myFunction() {

    var startRow = 2; // First row of data to process 
    var getlastrow_emailList =   sheet.getLastRow() - 1;
    var numRows = getlastrow_emailList; // Number of rows to process
    var dataRange = sheet.getRange(startRow, 1, numRows, 2);

     // Fetch values for each row in the Range.
       var data = dataRange.getValues();

        var value1 = paramValueSheet.getRange("A1").getValue();
        var value2 = paramValueSheet.getRange("A2").getValue();


    //  for (i in data) {   
         for (var i = 0; i < data.length; ++i) {
          var row = data[i];
        var emailAddress = row[0];  // First column 
        var emailSent = row[1]; // Second column


       if (emailSent != SEND_CONFIRMED) { // Prevents sending duplicates  

         var url = "https://www.SiteNameGoesHere.com/form?id=123456"; 
        UrlFetchApp.fetch(url +'&EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));

           sheet.getRange(startRow + i, 2).setValue(SENT_TAG);
          // Flush to make sure the cell is updated right away in case the script is interrupted
          SpreadsheetApp.flush();
       } 

      }

    //form submission
     var response = UrlFetchApp.fetch("https://www.FORM_URL_HERE.com/form?process=submit");

    }

更新1:

为了实现UrlFetchApp.fetchAll()以优化流程,以下是我正在使用的更新代码:

  //sheet refers to the sheet that includes email list (email list includes "Email" as a column header
    //paramValueSheet refers to the sheet that includes parameters values

var SENT_TAG = 'SEND_CONFIRMED';
var sheet = SpreadsheetApp.getActive().getSheetByName('EmailAddressSheet');
var paramValueSheet = SpreadsheetApp.getActive().getSheetByName('ParameterValuesSheet');

    function myFunction() {

    var startRow = 2; // First row of data to process 
    var getlastrow_emailList =   sheet.getLastRow() - 1;
    var numRows = getlastrow_emailList; // Number of rows to process
    var dataRange = sheet.getRange(startRow, 1, numRows, 2);

     // Fetch values for each row in the Range.
       var data = dataRange.getValues();

        var value1 = paramValueSheet.getRange("A1").getValue();
        var value2 = paramValueSheet.getRange("A2").getValue();

        var rqs = [];
        var ranges = [];
        for (var i = 0; i < data.length; ++i) {
          var row = data[i];
          var emailAddress = row[0];
          var emailSent = row[1];
          if (emailSent != SEND_CONFIRMED) {  // Should SEND_CONFIRMED be "SEND_CONFIRMED" or SENT_TAG?
            var url = "https://www.SiteNameGoesHere.com/form?id=123456"; 
            var req = UrlFetchApp.fetch(url +'&EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));
            SpreadsheetApp.getUi().alert(req);
            rqs.push(req);
            ranges.push("B" + (startRow + i)); // Modified
          }
        }
        UrlFetchApp.fetchAll(rqs);
        sheet.getRangeList(ranges).setValue(SENT_TAG); // Modified
        SpreadsheetApp.flush();



    }

此更新的代码引发以下错误:

"bad value" 在线UrlFetchApp.fetchAll(rqs);

要解决此问题,您可以看到我已在此更新的代码中添加了警报:

SpreadsheetApp.getUi().alert(req);

警报窗口向我显示了这样的值:

<!DOCTYPE html><html lang="en" class="no-js" data-reactroot=""><head><meta..so on..

这告诉我代码正在击中表单页面,并且页面正在呈现,UrlFetchApp.fetchAll(rqs);是导致此问题的原因。

更新2:

出于测试目的,我尝试在UPDATE 1代码的循环中更新以下行:

var req = UrlFetchApp.fetch(url +'&EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));

为此:

var req = UrlFetchApp.getRequest(url +'&EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));

*基本上使用getRequest()

在这种情况下,警报窗口SpreadsheetApp.getUi().alert(req); 向我显示此值[object Object]

这次错误出现在新的更新行上:

var req = UrlFetchApp.getRequest(url +'&EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));

错误说:

Attribute provided with invalid value: Header:X-Forwarded-For

脚本的执行甚至没有达到更新1中的UrlFetchApp.fetchAll(rqs);

我真的希望这有道理,如果我能得到帮助的话?

1 个答案:

答案 0 :(得分:0)

此修改如何?

修改点:

  • 在您的脚本中,URL被声明为url +'EMAIL=' + encodeURIComponent(emailAddress) + 'PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2)。在这种情况下,变得如下。
    • https://www.FORM_URL_HERE.com/form?&EMAIL={emailAddress}PARAM1={value1}&PARAM2={value2}
    • 在此修改中,此修改如下。
    • https://www.FORM_URL_HERE.com/form?EMAIL={emailAddress}&PARAM1={value1}&PARAM2={value2}
  • setValue()在for循环之外使用。这样,可以降低处理成本。
  • 在此修改中,rqs.push(UrlFetchApp.getRequest(...)); ... } proposed by tehhowch用于创建fetchAll方法的请求对象。

修改后的脚本:

请将您的for循环for (var i = 0; i < data.length; ++i) {...}替换为以下脚本,然后重试。

var rqs = [];
var ranges = [];
for (var i = 0; i < data.length; ++i) {
  var row = data[i];
  var emailAddress = row[0];
  var emailSent = row[1];
  if (emailSent != SEND_CONFIRMED) {  // Should SEND_CONFIRMED be "SEND_CONFIRMED" or SENT_TAG?
    var url = "https://www.FORM_URL_HERE.com/form?";
    var req = UrlFetchApp.getRequest(url +'EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));
    rqs.push(req);
    ranges.push("B" + (startRow + i)); // Modified
  }
}
UrlFetchApp.fetchAll(rqs);
sheet.getRangeList(ranges).setValue(SENT_TAG); // Modified
SpreadsheetApp.flush();

注意:

  • 在您的脚本中,未声明paramValueSheet中的SEND_CONFIRMEDif (emailSent != SEND_CONFIRMED) {AudienceList。尽管我认为这些声明可能会在其他地方声明,但请再次确认。
  • 关于SEND_CONFIRMED中的if (emailSent != SEND_CONFIRMED) {SEND_CONFIRMED应该是"SEND_CONFIRMED"还是SENT_TAG

参考文献:

我不确定您使用的API的规格。而且在我的环境中,我也不确定对端点的请求是否有效。关于此,请在您的环境中进行确认。对于这种情况,我表示歉意。

编辑1:

从您的评论中发现,以下脚本有效。

var url = "https://www.FORM_URL_HERE.com/form?";
UrlFetchApp.fetch(url +'&EMAIL=' + encodeURIComponent(emailAddress) + 'PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));

在这种情况下,URL如下。

https://www.FORM_URL_HERE.com/form?&EMAIL={emailAddress}PARAM1={value1}&PARAM2={value2}

如果这反映到修改后的脚本中,请进行如下修改。

从:
var req = UrlFetchApp.getRequest(url +'EMAIL=' + encodeURIComponent(emailAddress) + '&PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));
至:
var req = UrlFetchApp.getRequest(url +'&EMAIL=' + encodeURIComponent(emailAddress) + 'PARAM1=' + encodeURIComponent(value1) + '&PARAM2=' + encodeURIComponent(value2));

如果此修改无效,请确认emailAddressvalue1value2的所有值。而且,可能需要考虑同时访问Webform的数量的限制。

编辑2:

如果要通过拆分请求来请求URL,请将上面的脚本修改为以下脚本。

发件人:

UrlFetchApp.fetchAll(rqs);

收件人:

var numberInRequest = 100; // Number of URLs requested in one request.
var loop = Math.ceil(reqs.length / numberInRequest);
for (var i = 0; i < loop; i++) {
  UrlFetchApp.fetchAll(rqs.splice(0, numberInRequest)); Modified
}
  • 在这里,如果您想每100次请求一次,请将numberInRequest设置为100。