Google App Script Trigger Id Format

荒凉一梦 提交于 2019-12-01 11:20:53

I spent some hours on this, got some hair off. And I found this page. It has a piece of code that strangely works when you pass e.triggerUid in it, and not when using it directly :

function getFileByTriggerId(triggerId){
  var triggers = ScriptApp.getProjectTriggers();
  for(var i =0; i<triggers.length; i++){
    if(triggers[i].getUniqueId() == triggerId){
      return triggers[i].getTriggerSourceId();
    }
  }
}

Hope it will help someone

When you request the id of a trigger object using its getUniqueId() method, the value returned is a numerical String.

However when a function is called by the trigger, the triggerUid property of the event object will be that string converted to a Number.

The issue is that the string id often (but not always) expresses an integer value larger than the maximum integer value Apps Script can handle safely. When this happens the conversion from string to number results in the zeros in the least significant digits.

So, to compare the two properly you just need to convert the string id to a number, this ensures the same zeroing will occur.

someTrigger.getUniqueId() === event.triggerUid
// false - because the left side is a string, and the right is a number. 

Number(someTrigger.getUniqueId()) === event.triggerUid
// true - both sides are now numbers, the same number

someTrigger.getUniqueId() == event.triggerUid
// true - because using the standard comparison operator the string is automatically converted to a number in the background

Here's a note about strict v.s. standard comparison operations in Javascript.

Here's some Apps Script that demonstrates all of the above:

// Run onceOffClockTimer() and wait up to 1 min for the event to fire, then check your log. You might have to run it a few times to see a trigger id where the zeroing occurred

function onceOffClockTimer() {
  var newTriggerId = ScriptApp.newTrigger('timerCallbackFn')
    .timeBased()
    .after(5000)
    .create()
    .getUniqueId();
}


function timerCallbackFn(triggerEvent) {

  var eventTriggerId = triggerEvent.triggerUid,
    triggers = ScriptApp.getProjectTriggers();
  Logger
    .log('### Event Object ###')
    .log('id: %s', eventTriggerId)
    .log('id type: %s', typeof eventTriggerId)
    .log('id as String: %s\n', eventTriggerId.toString());

  var largestSafeInteger = 9007199254740991; // Obtained by Number.MAX_SAFE_INTEGER in a Chrome console 

  Logger
    .log('### Interesting Fact ###')
    .log('In Apps Script the largest safe integer is: %s\n', largestSafeInteger);

  for (var i = 0, x = triggers.length; i < x; i++) {

    var triggerID = triggers[i].getUniqueId();

    Logger
      .log('### Trigger Object [%s] ###', i)
      .log('id: %s', triggerID)
      .log('id type: %s', typeof triggerID)
      .log('id as Number: %s\n', Number(triggerID))

    Logger
      .log('### Comparisons ###')
      .log('Strict (Trigger Event ID === Trigger ID) is %s ', eventTriggerId === triggerID)
      .log('Strict (Trigger Event ID === Trigger ID as Number) is %s', eventTriggerId === Number(triggerID))
      .log('Direct (Trigger Event ID == Trigger ID) is %s', eventTriggerId == triggerID);
  }
}
Logger.log('' + triggerId);;;;

The trigger Id could be a large number (long 8 byte integer, or an even bigger number stored as an object), to overcome this, convert it to binary and then to 64 bit encoded string. This way you can safely store, and compare as well.

var v = Utilities.base64Encode(Utilities.newBlob(e.triggerUid).getBytes())

or to compare

if(Utilities.base64Encode(Utilities.newBlob(e.triggerUid).getBytes()) === Utilities.base64Encode(Utilities.newBlob(triggers[i].getUniqueId()).getBytes()))

As triggerId is a Number object and as such it is automatically converted to the exponential notation.

To handle this you can extend the Number.prototype to handle the correct representation.

Object.defineProperty(Number.prototype, 'toLongString', {
  value: function() {
    var parts = this.toString().split("e+");
    var first = parts[0].replace('.', "");
    var zeroes = parseInt(parts[1], 10) - (first.length - 1);

    var longString = first;

    for (var i = 0; i < zeroes; i++) {
      longString += "0";
    }

    return longString;
  }
});

function mainFunction(e) {
  var triggerId = e.triggerUid.toLongString();
  Logger.log(triggerId);
}

I had this same problem. The solution that worked for me was: toPrecision([numberOfDigits]).

For example:

([largenumber]).toPrecision(27)

Here is the source: https://teamtreehouse.com/community/covert-scientific-notation-within-variable-to-javascript-number-when-scientific-notation-is-yet-unknown

I hope that this helps someone!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!