异步循环不尊重异步

凯尔·杜里根(Kyle Durigan)

我在异步功能上有些卡住了。

我要完成的工作-我正在创建一个batchProcessing函数(batchGetSubs),该函数将遍历一组文件,读取ID,发出API请求,等待响应(THE ISSUE),然后写入新文件格式化数据的文件。

问题-我已经尝试了Async和Await,以及推送了诺言并尝试使用Promise.all来等待诺言被解决,但是没有成功。当前的行为是,在API调用实际返回所有数据之前,我获得了Promise.all部分中的所有console.logs。我已将这些文章用作参考:

守则-

async function batchGetSubs(data, command) {
    console.time('batchGetSubs')
    iteration = 1;
    let dataArray = []; promises = [];

    // LOOP THROUGH FILES, THEN GET TENANTS BY SUB
    for (i = iteration; i < totalIterations; i++) {
        let msIds = await loopAndDump(iteration);

        // LOOP THROUGH TENANTIDS AND GET SUBSCRIPTIONS
        msIds.map(async item => {
            let newRecord = await getSubsByTenantId(item);
            promises.push(await newRecord);
        });
        }
        Promise.all([promises]).then(() => { // FIXME: WHY IS THIS NOT WAITING FOR ALL RESPONSES?
            console.log(p1SubscriptionArray),
            console.timeEnd('batchGetSubs')
        });
    }



async function getSubsByTenantId(msTenantId) {
    let newRecord; let subscriptionArray = [];
    let bearerToken = p1BearerToken;
    let totalSubs = 0;
    const subIdConfig = {
        method: 'get',
        url: ``,
        headers: { 'Authorization': bearerToken }
    }
    await delay();
    await axios(subIdConfig)
        .then(async res => {
            console.log('AXIOS RESPONSE', res.data);
            if (res.data.items) {
                let subItems = res.data.items;
                console.log('^^^^^^^^^^^^^^^^^^', res.data.items)
                // LOOP THROUGH AND ADD TO SUBSCRIPTION ARRAY
                subItems.map(async subscription => {
                    if (subscription.friendlyName) {
                        totalSubs++;
                        subscriptionArray.push(subscription.friendlyName);
                    }
                });
                newRecord = { "tenantId": msTenantId, "totalSubs": totalSubs, "subscriptionFriendlyName": subscriptionArray };
            } else {
                // NO SUBS
                newRecord = { "tenantId": msTenantId, "totalSubs": totalSubs, "subscriptionFriendlyName": ['NONE'] };
                let statusCode, errorMessage;
                if (error && error.response === undefined) { // GETTING STATUS -4039 or -4077 INSTEAD OF 429 WHEN CHECKING SUBS. FORCE A RESEND.
                    if (error.errno && error.errno === -4039 || error.errno && error.errno === -4077) statusCode = 429; errorMessage = error.code;
                } else {
                    statusCode = error.response.status;
                    errorMessage = error.response.statusText;
                }
                console.error('ERROR:: SUBIDCONFIG SECTION THROWING ERROR: ', statusCode, portal, errorMessage);
                // SORT NON-200 CALLS BASED ON STATUS CODE
                switch (statusCode) {
                    case 403:
                        status403.push('subs', newRecord);
                        break;
                    case 404:
                        status404.push('subs', newRecord);
                        erroring = true;
                        break;
                    case 429:
                        status429.push('subs', newRecord);
                        erroring = true;
                        break;
                    default:
                        statusOther.push('subs', newRecord)
                        erroring = true;
                        break;
                }
            }
        })
        .catch(err => {
            newRecord = { "tenantId": msTenantId, "totalSubs": totalSubs, "subscriptionFriendlyName": ['NONE'] };
            console.error('ERROR: REQUEST IN GETSUBSBYTENANTID(): ', err)
        })
        .then(res => {
            console.log('DO WE HAVE ANY INFORMATION? ', newRecord);
            p1SubscriptionArray.push(newRecord);
            resolve();
        });
}
亭子

我只检查了第一个函数,即您在其中提出的问题:

为什么不等待所有回应?

有几个原因:

  1. promise调用时数组仍为空Promise.all这是因为您只在push 之后执行await,所以push异步发生(请阅读:稍后)。

  2. 即使在promises填充数组时,它也不会包含promise对象,但是会包含已解析的值(即,newRecord值)

  3. 即使promises将是一个promise数组,您也不会正确地将该数组传递给Promise.all:您将该数组包装在另一个数组中,该数组则只有一个条目,并且该条目不是promise,而是一个数组。

与您的问题无关,但:

  • 请养成显式声明所有变量的习惯。你没有做到这一点的iterationpromises也不i

  • .map在对返回值进行操作时使用。对于纯迭代,请使用.forEachfor在这种情况下,您可以使用返回值扩展promises数组。

  • 如果您打算致电batchGetSubs并需要知道何时完成,请确保它返回有用的承诺:return Promise.all()

这是对该功能的建议更正:

async function batchGetSubs(data, command) {
    console.time('batchGetSubs')
    let iteration = 1; // Declare!
    let dataArray = []; 
    let promises = []; // declare

    // declare i
    for (let i = iteration; i < totalIterations; i++) {
        let msIds = await loopAndDump(iteration);

        // Use the return value of the map method. No need for async callback
        promises.push(...msIds.map(item => {
            // Get the promise, not the resolved value, as that will come too late:
            return getSubsByTenantId(item);
        }));
    }
    // promises is already an array; don't make it an array of arrays.
    // And: return the resulting promise: it may be useful to the caller.
    return Promise.all(promises).then(() =>  {
        console.log(p1SubscriptionArray),
        console.timeEnd('batchGetSubs')
    });
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章