Student {! }'s Documents
Academic File Status: {!fileStatusText}
", "answerCount": 3, "upvoteCount": 0, "datePublished": "2019-08-27T07:07:11.000Z", "author": { "@type": "Person", "name": "upendra naidu", "url": "https://trailblazers.salesforce.com/profileView?u=0053A00000EywLVQAZ", "affiliation": { "@type": "Organization", "name": "IDFC First Bank Pvt Ltd" } }, "suggestedAnswer": [ { "@type": "Answer", "text": "To move your Visualforce (VF) page callouts to an **asynchronous** model, you must use **`@future(callout=true)`** Apex methods, as direct callouts from synchronous controller actions (like those choice advantage linked to `apex:actionFunction`) are forbidden. The overall architecture requires four steps: 1) The VF page's `apex:actionFunction` calls a new synchronous controller method (`DocumentCallDefaultAsync`). 2) This synchronous method immediately calls a separate static **`@future` method** (in a service class) to execute the actual external web service callout and stores the result (e.g., the JSON string) in a database record (like a custom status object). 3) The VF page uses an **`apex:actionPoller`** to periodically call a second synchronous controller method (`checkCalloutStatus`). 4) This status check method reads the database record; once it confirms the JSON result is present and the status is 'COMPLETE', the poller stops and the client-side JavaScript (e.g., `Tree1()`) renders the tree using the retrieved data.", "upvoteCount": 0, "url": "https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T46pbSAB", "datePublished": "2025-10-29T07:55:49.000Z", "author": { "@type": "Person", "name": "dona flint", "url": "https://trailblazers.salesforce.com/profileView?u=005KX000003dgbhYAA", "affiliation": { "@type": "Organization", "name": "--" } } } ] } }
Skip to main content
Hi Everyone,

Currently my VF page is run in synchronous mode now my requiremnt is that VF page will run asynchronously using callouts.

Any one have idea about this requirement please help me out.Below is the VF page and Controller.

=================================================================

VF page

<apex:page standardController="Opportunity" extensions="StudentDocumentsController" > 

    <link rel="stylesheet" href="{!URLFOR($Resource.JSTree1,'vakata-jstree-b83e2f6/dist/themes/default/style.min.css')}" />

    <script src="{!URLFOR($Resource.JSTree1,'vakata-jstree-b83e2f6/dist/libs/jquery.js')}"></script>

    <script src="{!URLFOR($Resource.JSTree1,'vakata-jstree-b83e2f6/dist/jstree.min.js')}"></script>

    <script type="text/javascript"> 

        var myWindow;

        function testfnx(documentId) {

            var docId = documentId.split("_");

            var u = '{!OrionODIViewerURL}' + docId[0] +'&syStudentID='+docId[1]+'&diDocumentsScheduledID='+docId[2]+'&diDocumentID='+docId[3]+'&syCampusID='+docId[4];//documentId;

            window.open(u);

        }

        window.onload = function (){

            //DocumentCallDefault();

        }

        function getTasks() {

            window.open("/apex/DisplayStudentTask?Id={!Id}",'Popup','height=400,width=1000,left=100,top=100,scrollbars=yes,toolbar=no,status=no'); 

        }

    </script>

    <script type="text/javascript">

        var jq1 = $.noConflict();

    </script>

    <style>

        span.tooltip {

            outline:none;

            escape:false; 

        }

        

        span.tooltip:hover {

            text-decoration:none;

            cursor: pointer;

        } 

        span.tooltip span {

            z-index:10;display:none; padding:14px 20px;

            margin-top:-50px; margin-left:18px;

            line-height:16px;

            border-radius:4px;

            -moz-border-radius: 4px;

            -webkit-border-radius: 4px;

                

            -moz-box-shadow: 5px 5px 8px ⌗CCC;

            -webkit-box-shadow: 5px 5px 8px ⌗CCC;

            box-shadow: 5px 5px 8px ⌗CCC;

        }

        span.tooltip:hover span{

            display:inline; position:absolute; color:⌗000000;

            border:1px solid ⌗000000; background:⌗CCCCCC; opacity:0.95;}//border:1px solid ⌗DCA; background:⌗D6F5F5; opacity:0.85;

        }

    </style>

    <apex:form id="wrap">

        <apex:actionFunction action="{!DocumentCallDefault}" name="DocumentCallDefault" status="callWebService" reRender="wrap,json,json1" oncomplete="Tree1();"/>

        <apex:actionFunction action="{!DocumentCallAll}" name="DocumentCallAll" status="callWebService" reRender="wrap,json,json1"  oncomplete="Tree2();"/>

        <apex:inputHidden value="{!jsonStr}" id="json"/>

        <apex:inputHidden value="{!jsonStr1}" id="json1"/>

        <apex:pageBlock id="docTree" tabStyle="Opportunity">

            <div style="text-align: center;">

                <input value="Load Student Documents" class="btn" title="Load Student Documents" name="load_student_documents" onclick="javascript:DocumentCallDefault();" type="button" />   

                <apex:commandbutton value="Get C-Code/Verification Tasks"  onclick="getTasks();"/>

                <apex:actionStatus id="callWebService">

                    <apex:facet name="stop">

                    </apex:facet>

                    <apex:facet name="start">

                        <apex:outputPanel >

                             &nbsp;<apex:image value="{!$Label.Image}" style="height: 16px; margin-top; 2px;"/>

                        </apex:outputPanel>

                    </apex:facet>

                </apex:actionStatus>

            </div>

            

            <table width="100%">

                <tr>

                    <td width="50%">

                        <div style="margin-top: 3px;margin-right: 0px;margin-bottom: 0px;margin-left: -2px;font-size: 1.0em;" width="100%" align="left"><b>Student {!currOpp.Account.Name}&apos;s Documents</b></div>

                    </td>

                    <td width="50%">

                        <div style="margin-top: 3px;margin-right: 0px;margin-bottom: 0px;margin-left: -8px;font-size: 1.0em;" width="100%" align="right"><b>Academic File Status: <img src="{!fileStatus}" width="12" hieght="12"/> {!fileStatusText}</b></div>

                    </td>

                </tr>

            </table>

            <apex:tabPanel switchType="client" value="{!selectedTab}">

                <apex:tab label="Default" name="Default" ontabenter="DocumentCallDefault()">

                    <div class="jstree1">

                    </div>

                </apex:tab>

                <apex:tab label="All" name="All" ontabenter="DocumentCallAll()">

                    <div class="jstree2">

                    </div>

                </apex:tab>

            </apex:tabPanel>

        </apex:pageBlock>

        <script>

            function Tree1(){

                var parsedJson = jq1.parseJSON(document.getElementById("{!$Component.wrap:json}").value);

                jq1('.jstree1').jstree(parsedJson);

            }

            function Tree2(){

                var parsedJson = jq1.parseJSON(document.getElementById("{!$Component.wrap:json1}").value);

                jq1('.jstree2').jstree(parsedJson);

                Tree1();

            }

        </script>

    </apex:form> 

</apex:page>

    

   

           

 
3 answers
  1. Oct 29, 2025, 7:55 AM

    To move your Visualforce (VF) page callouts to an **asynchronous** model, you must use **`@future(callout=true)`** Apex methods, as direct callouts from synchronous controller actions (like those choice advantage linked to `apex:actionFunction`) are forbidden. The overall architecture requires four steps: 1) The VF page's `apex:actionFunction` calls a new synchronous controller method (`DocumentCallDefaultAsync`). 2) This synchronous method immediately calls a separate static **`@future` method** (in a service class) to execute the actual external web service callout and stores the result (e.g., the JSON string) in a database record (like a custom status object). 3) The VF page uses an **`apex:actionPoller`** to periodically call a second synchronous controller method (`checkCalloutStatus`). 4) This status check method reads the database record; once it confirms the JSON result is present and the status is 'COMPLETE', the poller stops and the client-side JavaScript (e.g., `Tree1()`) renders the tree using the retrieved data.

0/9000