Hoppa till innehåll

Vänta på async JavaScript-funktion med löfte

JavaScript är asynkront och det gör det möjligt för oss att skapa webbplatser som kan svara på interaktion samtidigt som annat arbete utförs, en responsiv upplevelse. Ett asynkront beteende kan vara en utmaning när du vill se till att funktioner körs i en viss ordning eller när du bara vill köra en funktion om den föregående körningen är klar.

Du kan använda löften (promises) och await i JavaScript för att få kontroll över din kod och för att kunna vänta på att funktioner körs klart. En funktion som returnerar ett löfte (promise) kan man vänta på.

Den här koden har testats och fungerar med Google Chrome (75.0.3770.100), Mozilla Firefox (67.0.4), Microsoft Edge (42.17134.1.0), detta utan någon polyfill. Koden fungerar i Internet Explorer (11.829.17134.0) med polyfills för XMLHttpRequest och Promise. Om du vill stödja äldre webbläsare kan du läsa vårt inlägg om transpilering och komplettering av JavaScript.

Funktion som ska inväntas

Följande JavaScript-funktion skall anropas i intervaller, den är markerad som async och returnerar ett löfte. Den här funktionen returnerar resolve om anropet lyckades och reject om något gått fel.

async function getLog(log_name)
{
    // Return a promise
    return new Promise((resolve, reject) => {

        // Create form data
        var form_data = new FormData();
        form_data.append('LogName', log_name);

        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'https://mysite.com/api/getlog', true);
        xhr.onload = function () {

            // Check if the response is successful
            if (xhr.status === 200)
            {
                // Return a success response
                resolve(xhr.response);
            }
            else
            {
                // Return a reject response
                reject(xhr.status + " - " + xhr.statusText);
            }
        };
        xhr.onerror = function ()
        {
            // Return a reject response
            reject(xhr.status + " - " + xhr.statusText);
        };
        xhr.send(form_data);
    });

} // End of the getLog method

Vänta på att funktion ska slutföra körningen

Följande funktion anropar getLog-metoden i intervaller medan vi väntar på att en tidskrävande uppgift skall slutföras. Metoden getLog anropas med setTimeout tills det booleska värdet för finished är true. Den här koden ser till att vi inte anropar getLog flera gånger än nödvändigt.

async function syncFortnox(method)
{
    // Check if a lock is taken
    if (fortnoxlock.value === 'true') {
        toastr['error']('Du måste vänta tills den pågående processen blir klar.');
        return;
    }

    // Hide containers
    var collection = document.getElementsByClassName('hideable');
    for (var i = 0; i < collection.length; i++) {
        annytab.effects.slideUp(collection[i], 500);
    }

    // Lock the process
    fortnoxlock.value = 'true';

    // Get a log window reference
    var container = document.getElementById('log-window');

    // Start a loading animation
    //$('#log-window').html('<div class="annytab-basic-loading-container"><i class="fas fa-spinner fa-pulse fa-4x fa-fw"></i><div class="annytab-basic-loading-text">Arbetar ...</div></div>');
    container.innerHTML = '<div style="color:#4CAF50;"><i class="fas fa-spinner fa-pulse fa-fw"></i> Arbetar ...</div>';

    // Get fortnox api values
    var nox_api_values = new Object();
    nox_api_values.AccessToken = document.getElementsByName('txtAccessToken')[0].value;
    nox_api_values.PriceList = document.getElementsByName('txtPriceList')[0].value;
    nox_api_values.PenaltyInterest = parseInt(document.getElementsByName('txtPenaltyInterest')[0].value) / 100;
    nox_api_values.SalesVatTypeSE = document.getElementsByName('selectSalesVatTypeSE')[0].value;
    nox_api_values.SalesAccountSE25 = document.getElementsByName('txtSalesAccountSE25')[0].value;
    nox_api_values.SalesAccountSE12 = document.getElementsByName('txtSalesAccountSE12')[0].value;
    nox_api_values.SalesAccountSE6 = document.getElementsByName('txtSalesAccountSE6')[0].value;
    nox_api_values.SalesAccountSE0 = document.getElementsByName('txtSalesAccountSE0')[0].value;
    nox_api_values.SalesAccountSEREVERSEDVAT = document.getElementsByName('txtSalesAccountSEREVERESEDVAT')[0].value;
    nox_api_values.SalesAccountEUVAT = document.getElementsByName('txtSalesAccountEUVAT')[0].value;
    nox_api_values.SalesAccountEUREVERSEDVAT = document.getElementsByName('txtSalesAccountEUREVERESEDVAT')[0].value;
    nox_api_values.SalesAccountEXPORT = document.getElementsByName('txtSalesAccountEXPORT')[0].value;
    nox_api_values.PurchaseAccount = document.getElementsByName('txtPurchaseAccount')[0].value;
    nox_api_values.StockArticle = (document.getElementsByName('cbStockArticle')[0].value === 'true');
    nox_api_values.StockAccount = document.getElementsByName('txtStockAccount')[0].value;
    nox_api_values.StockChangeAccount = document.getElementsByName('txtStockChangeAccount')[0].value;
    nox_api_values.OnlyAllowTrustedSenders = (document.getElementsByName('cbTrustedSenders')[0].value === 'true');

    // Get a guid
    var guid = getGuid();

    // Get the log file name
    var log_name = dox_api_values.ApiEmail + "/" + guid + ".log";

    // Get logs every second
    var finished = false;
    setTimeout(async function run()
    {
        var response = '';

        try
        {
            // Get log information and wait for a response
            response = await getLog(log_name);
        }
        catch (err)
        {
            console.log(err);
        }
                
        if (finished === true)
        {
            // Print to log window and return
            printToLogWindow(container, response, finished);
            return;
        }
        else
        {
            // Print to log window and run again
            printToLogWindow(container, response, finished);
            setTimeout(run, 500);
        }
                
    }, 1000);

    // Create form data
    var form_data = new FormData();
    form_data.append('Guid', guid);
    form_data.append('DoxservrApiValues', JSON.stringify(dox_api_values));
    form_data.append('FortnoxApiValues', JSON.stringify(nox_api_values));

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'https://mysite.com/api/' + method, true);
    xhr.onload = function () {

        // Check if the response is successful
        if (xhr.status === 200) {

            // Mark the process as finished
            finished = true;
            //clearTimeout(timeout);
        }
        else
        {
            // Output error information
            toastr['error'](xhr.status + " - " + xhr.statusText);
        }

        // Release the lock
        fortnoxlock.value = 'false';
    };
    xhr.send(form_data);

} // End of the syncFortnox method
Etiketter:

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *