繁体   English   中英

与 javascript Promise 斗争

[英]Struggling with javascript Promise

我正在努力让 javascript Promises 工作。
我正在寻找一两个关于我做错了什么的指针。 下面是我的代码。 我正在尝试将loadUserPayRateWrapped()转换为从数据库获取数据的函数。 我得到的行为是,在$.getJSON()有机会获取它的数据之前,整套包装器代码仍在返回。

等待数据请求的函数:

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" );

    });

}

包装承诺函数:

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

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

异步调用者:

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

    }
}

来自想要数据的主线的代码:

// 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

只需将$.getJSON从回调样式“转换” $.getJSON Promise 就足够了。

这是我的例子,也许你自己处理过错误情况。

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)
      }
    });
  });
}

现在, loadUserPayRateWrapped返回一个 Promise。 然后你可以使用 Promise 风格来调用函数,或者使用async/await风格:

// 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));
})();

我没有使用您绝对可以使用的$.fetchJSON ,而是使用window.fetch来做到这一点。 并添加了asyncawait以便我们不使用then块。

// Added async
async function loadUserPayRateWrapped( projectId )
{

    var URI = "/projects/getAssignedResponsibilities?projectId=" + projectId;
    
    // Modified this line
    const data = await window.fetch(URI);

    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;
        } );
    }

    return getDataFromCookie( "payRate" );

}

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

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

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

    }
}

此外,在以下块中

$.each( altPayArray, function ( idx, element ) {
    if ( element.uid == employeeId )
        return element.pay;
});

从函数内部返回element.pay将导致它将值返回给内部函数而不是外部函数。 所以相反,你可以做

for (const element of altPayArray) {
    if ( element.uid == employeeId ) {
        return element.pay;
    }
}

您需要在loadUserPayRatePromise处返回承诺

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

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

你只想从你的函数中返回一个 promise,不要命名它。

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

使它们异步

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM