我在异步功能上有些卡住了。
我要完成的工作-我正在创建一个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();
});
}
我只检查了第一个函数,即您在其中提出的问题:
为什么不等待所有回应?
有几个原因:
promise
调用时,数组仍为空Promise.all
。这是因为您只在push
之后执行await
,所以push
异步发生(请阅读:稍后)。
即使在promises
填充数组时,它也不会包含promise对象,但是会包含已解析的值(即,newRecord
值)
即使promises
将是一个promise数组,您也不会正确地将该数组传递给Promise.all
:您将该数组包装在另一个数组中,该数组则只有一个条目,并且该条目不是promise,而是一个数组。
与您的问题无关,但:
请养成显式声明所有变量的习惯。你没有做到这一点的iteration
,promises
也不i
。
仅.map
在对返回值进行操作时使用。对于纯迭代,请使用.forEach
或for
。在这种情况下,您可以使用返回值扩展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] 删除。
我来说两句