2

My lightning component has a button that shows a dialog when clicked. To show that dialog, i need to call a server-side action and parse the response. When I enqueue the action, it takes a long time to execute - or sometimes it seems I have to click the button twice to batch another request before it's processed. I need this to be responsive to the user - no one's going to wait 10 seconds for this action to be dequeued. What can I do to execute this immediately from my helper? Here's my code:

MyComponentRenderer.js

({
    afterRender: function(component, helper) {
        this.superAfterRender();

        // listen to iframe messages
        this.processMessageWrapper = function(e) {
            helper.processMessage(e, component);
        }
        addEventListener("message", this.processMessageWrapper, false);
    },

    unrender: function(component, helper) {
        this.superUnrender();
        window.removeEventListener("message", this.processMessageWrapper);
    },

    processMessageWrapper: function(e) {}
})

MyComponentHelper.js

({
  processMessage: function(e, component) {
    var getValidHostsForOrg = component.get("c.getValidHostsForOrg");

    getValidHostsForOrg.setCallback(this, function(response) {
      var state = response.getState();
      if (state === "SUCCESS") {
        var isValidOrigin = false;
        var validOrigins = response.getReturnValue();
        var host = this.extractHostname(e.origin);

        for (var i = 0; i < validOrigins.length; i++) {
            if (host.match(validOrigins[i])) {
              isValidOrigin = true;
              break;
            }
        }

        if (!isValidOrigin)
          return;

        var eventName = "e." + e.data.eventName;
        var eventArgs = e.data.eventArgs;
        var event = $A.get(eventName);
        if (event) {
            event.setParams(eventArgs);
            event.fire();
        }

      } else if (state === "ERROR") {
          var errors = response.getError();
          if (errors) {
              if (errors[0] && errors[0].message) {
                  console.log("Error message: " + 
                           errors[0].message);
              }
          } else {
              console.log("Unknown error");
          }
      }
    });

    $A.enqueueAction(getValidHostsForOrg);
  },

  extractHostname: function(url) {
    var hostname;
    //find & remove protocol (http, ftp, etc.) and get hostname

    if (url.indexOf("://") > -1) {
      hostname = url.split('/')[2];

    } else {
      hostname = url.split('/')[0];
    }

    //find & remove port number
    hostname = hostname.split(':')[0];
    //find & remove querystring
    hostname = hostname.split('?')[0];

    return hostname;
  }
})

MyComponent.cmp

<aura:component access="global" controller="ServerSideController" implements="flexipage:availableForAllPageTypes,force:hasRecordId,force:hasSObjectName">

    <!-- designer attributes -->
    <aura:attribute access="global" name="objectName" type="String" default="Opportunity" required="true"/>
    <aura:attribute access="global" name="relationshipName" type="String"/>
    <aura:attribute access="global" name="height" type="Integer" default="600" />
    <aura:attribute access="global" name="viewID" type="String" />
    <!-- internal attributes -->
    <aura:attribute name="vfUrl" type="String" />

    <div class="container" style="{!'height:' + v.height + 'px;'}">
        <iframe class="iframe" aura:id="vfIframe" seamless="true" src="{!v.vfUrl}"></iframe>
    </div>

    <aura:handler name="init" action="{!c.auraInit}" value="{!this}"/>
</aura:component>
  • Not sure you can. The issue may also not be with the time to send to server but also may be with the time for the server to process and return a response. I have some orgs that a callout and update of an object takes up to 2 minutes due to all they have going on. Just FYI as I know it does not help much – Eric Jul 19 '17 at 17:59
  • Thanks @Eric. I know the delay isn't with the server.. i can execute it once, observe the delay - consistently.. then just double click and BOTH come back immediately after my second click. it's gotta be waiting for a batch of requests. I'm wondering if there's even a different way of doing this without the whole queuing business. even just an ajax http request. – Donuts Jul 19 '17 at 18:05
  • As an aside, the framework manages both foreground and background requests in two separate queues. The option to send an action into the background queue can be of great help in certain use cases. developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – Mark Pond Jul 19 '17 at 19:22
2

There was definitely something wrong with my code. The queue shouldn't take that long to process my request. I was missing a $A.getCallback() around my processMessageWrapper(). It executes immediately now.

({
    afterRender: function(component, helper) {
        this.superAfterRender();

        // listen to iframe messages
        // I WAS MISING THIS CALL TO $A.getCallback()
        this.processMessageWrapper = $A.getCallback(function(e) {
            helper.processMessage(e, component);
        });

        addEventListener("message", this.processMessageWrapper, false);
    },

    unrender: function(component, helper) {
        this.superUnrender();
        window.removeEventListener("message", this.processMessageWrapper);
    }
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.