当前位置: 首页 > 知识库问答 >
问题:

异步循环不遵守异步

屈晨
2023-03-14

我对一个异步函数有点拘泥于此。

我要完成的是创建一个batchProcessing函数(batchGetSubs),它将循环访问一组文件,读取一个ID,然后发出一个API请求,等待一个响应(问题),然后用格式化的数据写入一个新文件。

问题--我尝试了异步和等待,以及推送承诺和尝试使用承诺.所有这些都是为了等待承诺的解决,但没有成功。当前的行为是,在API调用实际返回所有数据之前,我获取Promission.all部分中的所有console.logs。我引用了这些文章作为参考:

  • javascript for循环内部的异步进程
  • 用Axios承诺全部
  • JavaScript承诺将值推入数组(仅从函数或外部?)

密码-

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

共有2个答案

唐运诚
2023-03-14

你做一个等待然后在同一时间。你做一个承诺/然后或等待/异步

async function getSubsByTenantId(msTenantId) {
    let newRecord; let subscriptionArray = [];
    let bearerToken = p1BearerToken;
    let totalSubs = 0;
    const subIdConfig = {
        method: 'get',
        url: ``,
        headers: { 'Authorization': bearerToken }
    }
    await delay();
    const r = await axios(subIdConfig)
    const reponse = r.data
    console.log(response)
}

如果要尝试catch,请执行以下操作:

async function getSubsByTenantId(msTenantId) {
    let newRecord; let subscriptionArray = [];
    let bearerToken = p1BearerToken;
    let totalSubs = 0;
    const subIdConfig = {
        method: 'get',
        url: ``,
        headers: { 'Authorization': bearerToken }
    }
    await delay();
    let r
    try {
      r = await axios(subIdConfig)
    } catch (error) {
     console.log(error)
    }
    const reponse = r.data
    console.log(response)
}
屈晨
2023-03-14

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

为什么这不是等待所有的回应呢?

有几个原因:

>

  • 调用promise.all时,promise数组仍然为空。这是因为您只在await之后执行push,因此push是异步发生的(稍后阅读)。

    即使填充了promission数组,它也不会包含promissions对象,而是解析值(即newrecord值)

    即使promission是promissions的数组,您也没有将该数组正确传递给promission.all:您将该数组包装在另一个数组中,然后该数组只有一个条目,而该条目不是promission,而是一个数组。

    与您的问题无关,但:

    >

  • 请养成显式声明所有变量的习惯。您没有为迭代承诺i执行此操作。

    仅在使用返回值执行某些操作时使用.map。对于纯迭代,请使用.foreachFor。在这种情况下,可以使用返回值扩展promission数组。

    如果您打算调用BatchGetSubs并需要知道何时完成所有操作,那么请确保它返回一个有用的承诺:returnpromise.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')
        });
    }
    

  •  类似资料:
    • 问题内容: 我需要一个等待异步调用然后继续的循环。就像是: 我该怎么办?你有什么想法? 问题答案: 如果阻止脚本和浏览器,则无法在JavaScript中混合使用同步和异步。 您需要在此处采用完整的事件驱动方式,幸运的是我们可以将丑陋的东西藏起来。 编辑: 更新了代码。 这将为我们提供一个异步方法,您当然可以进一步修改它,例如使用一个检查循环条件的函数等。 现在进行测试: 并输出:

    • 问题内容: 我是这个Node.js的新手..我对此回调有点困惑..在我的应用程序中,我在for循环内调用异步函数调用,我想我的问题是在得到异步调用响应之前, for循环被循环。 我的代码: 搜索功能代码: 我想在成功执行1个搜索功能后执行for循环,我想我必须使用async for loop。请指导我解决此问题。 问题答案: 我将您的代码示例简化为以下几行,以使您更容易理解该概念。 先前代码的问题

    • 本文向大家介绍JavaScript 异步等待循环,包括了JavaScript 异步等待循环的使用技巧和注意事项,需要的朋友参考一下 示例 在循环中使用异步等待时,您可能会遇到其中一些问题。 如果您只是尝试在内部使用await forEach,则会抛出Unexpected token错误。 这是因为您错误地将箭头功能视为一个块。该await会在回调函数,这是不是上下文async。 解释器可以防止我们

    • 问题内容: 这个问题已经在这里有了答案 : 循环内的JavaScript封闭-简单的实际示例 (44个答案) 2年前关闭。 我正在运行以下形式的事件循环: 我正在尝试显示一系列警报,显示从0到10的数字。问题是,当触发回调函数时,循环已经经历了几次迭代,并且显示了更高的值。有关如何解决此问题的任何建议? 问题答案: 在启动所有异步操作时,循环将立即运行到完成。当他们将来完成某个时间并调用其回调时,

    • 本文向大家介绍JavaScript 异步操作和事件循环,包括了JavaScript 异步操作和事件循环的使用技巧和注意事项,需要的朋友参考一下 示例 常见的JavaScript编程环境中许多有趣的操作都是异步的。例如,在浏览器中,我们看到类似 在Node.js我们看到的东西像 这与事件循环如何配合? 这是如何工作的,当这些语句执行时,它们告诉主机环境(即Node.js分别为浏览器或运行时)关闭并可

    • 问题内容: 事情是:我有一个页面,其中必须显示未确定数量的图像,这些页面是通过AJAX(在服务器端使用base64编码)一张一张地加载的。 问题是仅当获取所有图像时,才将图像(由renderImageData()函数构造)附加到所有DIV中(一起)。我的意思是,直到循环结束,才有可能进行任何DOM操作。 由于可能会有大量的图像,因此我需要一张一张地加载和显示图像,因此我无法将它们堆叠起来,直到将它