javascript中嵌套循环异步调用



我有一个对象数组

const items = [
{
quantity: '2',
name: 'john',
type: 'https://api/event/1',
},
{
quantity: '3',
name: 'jane',
type: 'https://api/event/2',
}
]

对于数组中的每个对象,我需要根据对象的quantity值调用APIn次数。调用API基本上会生成一个唯一的链接。我知道这对性能来说不是最好的,但这是一个小应用程序,在最坏的情况下,我们会调用3-5个api,通常是1个。在这种情况下,我在数组中有2个对象,第一个有2个API调用,第二个有3个API调用。每次我调用API时,我都想将结果(唯一链接)保存在一个数组中,以便我可以将它们通过电子邮件发送给购买它们的客户。

这是我到目前为止尝试过的,但它没有工作:


const promises = []
const getLinks = async (arr) => {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr[i].quantity; j++) {
const getLink = (owner) => {
axios.request({
method: 'POST',
url: 'https://api.call'
})
.then(function (response) {              
const promise = response.data.url
promises.push(promise)
})
.catch(error => console.log(error))
}
}
}
const links = await Promise.all(promises)
console.log('links:', links)  // === [] this is always empty ===
}
getLinks(items)

我学到的一件事是await不能并且会在循环中大幅降低代码速度

我似乎不能使它工作

  • getLink在你的代码中从来没有被调用过。
  • 即使它被调用,当Promise.all(promises)运行时,promises数组仍然是空的,因为它在then回调中填充,稍后运行
  • 您正在将url从响应推送到数组,而不是推送axios返回的实际承诺
const promises = []
for (const o of items) {
for (let i = 0; i < o.quantity; i++) {
const promise = axios.request({ method: post, url: o.type })
promises.push(promise)
}
}
const responses = await Promise.all(promises)
const urls = responses.map(r => r.data.url)

,或者您可以使用flatMap获取axios返回的所有承诺的数组,并在结果数组

上使用Promise.all
const promises = items.flatMap(o => 
Array.from({ length: o.quantity }, _ => axios.request({ method: post, url: o.type })
)
const responses = await Promise.all(promises)

你对承诺的工作方式有点困惑。

/* THIS THING IS A PROMISE -> */ axios.request({
method: 'POST',
url: 'https://api.call'
})
.then(function (response) {              
const promise = response.data.url // <-THIS THING IS NOT A PROMISE
})

Promiseaxios.request()的值。因此,如果你想要这个承诺,你应该这样做:

const promise = axios.request();

.then()里面的值是NOTaPromise!!它是promise返回的值:

const promoise = axios.request({
method: 'POST',
url: 'https://api.call'
})
.then(function (response) {              
const result = response.data.url;
return result;
})

因此,您一直在向promises数组推送完全错误的东西!你一直在推送api调用返回的URL字符串,而不是承诺。

让你的代码正常工作是非常简单的:

const getLinks = async (arr) => {
let promises = []
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr[i].quantity; j++) {
const getLink = (owner) => {
const promise = axios.request({
method: 'POST',
url: 'https://api.call'
})
.then(function (response) {              
return response.data.url
})
.catch(error => console.log(error))
promises.push(promise)
}
}
}
const links = await Promise.all(promises)
console.log('links:', links)
}
//Map methods return an array
const apiResponse = items.map(async(apiCall) => {
// call an api here and store its result in a veriable 
let returnedResult
await axios.get(apiCall.type)
.then(response => {
//refactor the reponse to how you want to store it in the array
returnedResult = response
})
return returnedResult
})
Promise.all(apiResponse)
.then(response => {
console.log(response)
// sent an email here based on the response you get
})

// Update your code like the following, I tested on my side and its working and easy
const axios = require("axios");
const items = [
{
quantity: "2",
name: "users",
type: "https://jsonplaceholder.typicode.com/users/1",
},
{
quantity: "3",
name: "posts",
type: "https://jsonplaceholder.typicode.com/posts/1",
},
];
const allPromises = items
.map((eachObject) => {
const { type: url, quantity } = eachObject;
const promiseArray = new Array(Number(quantity)).fill(axios.get(url));
return promiseArray;
})
.reduce((prev, current) => {
return [...prev, ...current];
}, []);
Promise.all(allPromises)
.then((res) => {
if (res instanceof Array) {
const result = res.map((each) => each.data);
console.log("result is", result);
} else {
console.log("not an array");
}
})
.catch((err) => console.error(err))
.finally(() => console.log("done!"));

相关内容

  • 没有找到相关文章

最新更新