Google Apps Script Async function execution on Server side

前端 未结 2 1386
心在旅途
心在旅途 2020-12-20 05:18

I have a GMail add-on which uses CardService for UI. Some of the callback functions for the Card actions take over than 30 sec. Thus, I\'m getting the following error.

相关标签:
2条回答
  • 2020-12-20 05:49

    As of now, there is no asynchronous execution for the Gmail add-on. Even if there is something, there is no way to refresh the UI without user action.

    But, there is a hack. What you can do is, if there is a long running process is there, just create a "openlink" action (set link), which should open a url (https://yourhtmlpageurl?redirect_uri=) with html response. This html can have jquery ajax call, which can wait for some time. Once you get the response in the html window, redirect the page to the redirect_uri that is passed by passing the response data. So, our add on will get a callback to the function with parameter as json object with all the query parameters to the redirect_uri. Once you get the expected response, cache the response by using CacheService. return some html success template, which should automatically close the window by itself.

    For Creating openlink action:

    For generating redirect script URI with state token:

    function generateNewStateToken(callbackName, user_info) {
    return ScriptApp.newStateToken()
    .withMethod(callbackName)
    .withArgument("user_info", JSON.stringify(user_info))
    .withTimeout(3600)
    .createToken();
    }
    
    function getRedirectURI() {
        return "https://script.google.com/macros/d/" + ScriptApp.getScriptId() + "/usercallback";
    }
    
    var htmlUrl = <your_html_url> + "?redirect_uri="+ getRedirectURI() + "&state=" + generateNewStateToken("asyncCallback", {});
    
    CardService.newOpenLink().setUrl(htmlUrl).setOpenAs(CardService.OpenAs.OVERLAY).setOnClose(CardService.OnClose.RELOAD_ADD_ON);
    
    function asyncCallback(data) {
        data.response; // response which you can pass from script
        CacheService.getUserCache().put("long_running_process_resp", data.response);
        data.user_info; // user_info passed during state token creation
        // cache the data using cache service
        return HtmlService.createHtmlOutputFromFile("success");
    }
    

    success.html:

    <!DOCTYPE html>
    <html>
    
      <head>
        <base target="_top">
        <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
      </head>
      <body>
        <div class="sidebar">
            <p>Long running Process completed.</p>
        </div>
      </body>
      <script>
      setTimeout(function() {
        top.window.close();
      }, 2000);
      </script>
    </html>

    Once the success.html is closed by itself, there will be a refresh of the gmail add on. So, you can lookup for the long running response data from CacheService.

    Let me know if you have any more questions on this process.

    0 讨论(0)
  • 2020-12-20 05:58

    Sabbu's answer is pretty good. But, if you want to trigger the long running process without expecting the user to click on the openlink, you can render an image using: CardService.newImage().setImageUrl('https://yourservice.com/pixel/action.png?name=value&_nocache='+new Date().getTime())

    On the server side, you can map the path '/pixel/action.png' to the long running code which returns a tiny transparent pixel (1x1) on complete: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==

    0 讨论(0)
提交回复
热议问题