Search code examples
javascriptpromisees6-promise

Struggling with javascript Promise


I'm struggling to get get javascript Promises to work.
I'm looking for a pointer or two on what I'm doing wrong. Below is my code. I'm trying to convert loadUserPayRateWrapped() into a function that gets data from a database. The behavior I'm getting, is that the whole set of wrapper code is still returning before $.getJSON() has had a chance to get it's data.

The function that is waiting for the data request:

function loadUserPayRateWrapped( projectId )
{

    var URI = "/projects/getAssignedResponsibilities?projectId=" + projectId;
    $.getJSON( URI, function ( data )
    {
        if ( data === null )
            return getDataFromCookie( "payRate" );
        else
        {
            const employeeId = getDataFromCookie( "empId" );
                    if ( data[ 0 ].alternatePay === null )
                return getDataFromCookie( "payRate" );
                    var altPayArray = JSON.parse( data[ 0 ].alternatePay );
                    $.each( altPayArray, function ( idx, element )
            {
                if ( element.uid == employeeId )
                    return element.pay;
            } );
        }

        // nothing was found, so return the regular pay rate
        return getDataFromCookie( "payRate" );

    });

}

The wrapper promise function:

function loadUserPayRatePromise( projectId )
{
    var payRateProm = new Promise((resolve, reject) =>
    {
        var payRate = loadUserPayRateWrapped( projectId );
        resolve( payRate );
    });

    payRateProm.then( result => { return payRate } );
}

The async caller:

async function loadUserPayRate( projectId )
{
    try
    {
        const pay = await loadUserPayRatePromise( projectId );
        return pay;
    }
    catch(error)
    {

    }
}

code from the mainline that wants the data:

// add the default pay rate for this user
var payRate = loadUserPayRate( data.projectId );
$( "#hourlyRate" ).val( payRate.toFixed(2) );    //payRate must be populated before this line

Solution

  • Just "convert" $.getJSON from callback style to Promise is required and enough.

    This is my example, maybe you have handle error case by yourself.

    function loadUserPayRateWrapped(projectId) {
      return new Promise((resolve, reject) => { // wrap callback function into a promise
        var URI = "/projects/getAssignedResponsibilities?projectId=" + projectId;
        $.getJSON(URI, function (data) {
          const defaultPayRate = getDataFromCookie("payRate"); // extract to variable to reuse
          if (data === null) { // recommend style: if block with {}
            return resolve(defaultPayRate);
          } else {
            const employeeId = getDataFromCookie("empId");
            if (data[0].alternatePay === null) {
              return resolve(defaultPayRate);
            }
            var altPayArray = JSON.parse(data[0].alternatePay);
            var foundAltPay = altPayArray.find(p => p.uid === employeeId); // why $.each ??
            // nothing was found, so return the regular pay rate
            return resolve(foundAltPay || defaultPayRate)
          }
        });
      });
    }
    

    Now, loadUserPayRateWrapped return a Promise. Then you can use Promise style to call the function, or use async/await style:

    // Promise style
    loadUserPayRateWrapped(data.projectId)
      .then(payRate => {
        $("#hourlyRate").val(payRate.toFixed(2));
      });
    
    // async/await style with IIFE
    (async () => {
      const payRate = await loadUserPayRateWrapped(data.projectId); // wait
      $("#hourlyRate").val(payRate.toFixed(2));
    })();