Node.js - 承诺不在循环内解决
Node.js - Promise not resolving within loop
大家好,
我正在使用 Axios for Node.js 从 PipeDrive 的 API 中提取一些数据。 PipeDrive 开发其 API 分页的方式有点不同。这是他们的分页指示器的外观:
"additional_data": {
"pagination": {
"start": 0,
"limit": 100,
"more_items_in_collection": true,
"next_start": 100
}
}
我需要遍历所有页面以提取数据,我的代码已成功完成,但由于某种原因我无法得到解决的承诺。
我的代码逻辑如下:
if(more_items_in_collection){Add current page's data then re-run the same function with the next_start as a parameter}
else{Add current page's data then RESOLVE the promise to complete the function}
但是这个解决方案永远不会发生,即使我的代码有效(奇怪)。
大师,能否请您看看我的代码并告诉我为什么您认为它无法解析(function().then((result) => {OUTPUT})
从未 returns 发生)?
一如既往的感谢!
const queryPipeDrive = (start) =>{
// Query is a full then-able Async function
return new Promise((resolve, reject) => {
// API CALL
axios({
method: 'GET',
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start
}
})
// THEN DO THIS
.then((response) => {
// IF there are more items in collection on additional pages, iterate through the pages
if(response.data.additional_data.pagination.more_items_in_collection){
// Add all deals on page to the container
for (const deal of response.data.data) {
db.get('deals').push(deal) // Push deal data to the StormDB File
}
console.log(chalk.cyan(`${response.data.additional_data.pagination.next_start}`))
// Function loop created. We will loop UNTIL the 'more_items_in_collection' prop is false, then we'll resolve the promise.
queryPipeDrive(response.data.additional_data.pagination.next_start)
}else{
// Add all deals on this page to the reponse container
for (const deal of response.data.data) {
db.get('deals').push(deal)
}
db.save() // Save changes to temp DB
resolve(response.data.data) // Resolve Promise with the data from the successful call
}
})
.catch((err) => {
console.log(chalk.red(err))
reject(err)
})
})
}
您的 more_items_in_collection 案例永远无法兑现承诺。它只是创建一个新的,然后什么也不做。
此外,使用 new Promise
会使代码变得比需要的更复杂。 Axios 已经 return 是一个承诺,所以没有必要明确地创建一个新的。调用 .then
将自动创建一个新的承诺,它解析为您在回调中 return 的任何值。
const queryPipeDrive = (start) => {
// API CALL
return axios({
method: "GET",
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start,
},
})
// THEN DO THIS
.then((response) => {
// IF there are more items in collection on additional pages, iterate through the pages
if (response.data.additional_data.pagination.more_items_in_collection) {
// Add all deals on page to the container
for (const deal of response.data.data) {
db.get("deals").push(deal); // Push deal data to the StormDB File
}
console.log(
chalk.cyan(`${response.data.additional_data.pagination.next_start}`)
);
// Function loop created. We will loop UNTIL the 'more_items_in_collection' prop is false, then we'll resolve the promise.
return queryPipeDrive(
response.data.additional_data.pagination.next_start
);
} else {
// Add all deals on this page to the reponse container
for (const deal of response.data.data) {
db.get("deals").push(deal);
}
db.save(); // Save changes to temp DB
return response.data.data;
}
})
.catch((err) => {
console.log(chalk.red(err));
throw err;
});
};
除了已接受的答案。
你会考虑在 await 中使用这个异步函数吗?这样,你就调用了main()
.
const main = async start => {
const res = await queryPipeDrive(start);
if (res.isMoreItems === true) {
await main(res.nextStart);
}
};
async function queryPipeDrive(start) {
const response = await axios({
method: "GET",
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start,
},
});
for (const deal of response.data.data) {
db.get("deals").push(deal);
}
if (response.data.additional_data.pagination.more_items_in_collection) {
console.log(
chalk.cyan(`${response.data.additional_data.pagination.next_start}`)
);
return {
isMoreItems: true,
nextStart: response.data.additional_data.pagination.next_start,
};
} else {
db.save(); // Save changes to temp DB
return {
isMoreItems: false,
};
}
}
大家好,
我正在使用 Axios for Node.js 从 PipeDrive 的 API 中提取一些数据。 PipeDrive 开发其 API 分页的方式有点不同。这是他们的分页指示器的外观:
"additional_data": {
"pagination": {
"start": 0,
"limit": 100,
"more_items_in_collection": true,
"next_start": 100
}
}
我需要遍历所有页面以提取数据,我的代码已成功完成,但由于某种原因我无法得到解决的承诺。
我的代码逻辑如下:
if(more_items_in_collection){Add current page's data then re-run the same function with the next_start as a parameter}
else{Add current page's data then RESOLVE the promise to complete the function}
但是这个解决方案永远不会发生,即使我的代码有效(奇怪)。
大师,能否请您看看我的代码并告诉我为什么您认为它无法解析(function().then((result) => {OUTPUT})
从未 returns 发生)?
一如既往的感谢!
const queryPipeDrive = (start) =>{
// Query is a full then-able Async function
return new Promise((resolve, reject) => {
// API CALL
axios({
method: 'GET',
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start
}
})
// THEN DO THIS
.then((response) => {
// IF there are more items in collection on additional pages, iterate through the pages
if(response.data.additional_data.pagination.more_items_in_collection){
// Add all deals on page to the container
for (const deal of response.data.data) {
db.get('deals').push(deal) // Push deal data to the StormDB File
}
console.log(chalk.cyan(`${response.data.additional_data.pagination.next_start}`))
// Function loop created. We will loop UNTIL the 'more_items_in_collection' prop is false, then we'll resolve the promise.
queryPipeDrive(response.data.additional_data.pagination.next_start)
}else{
// Add all deals on this page to the reponse container
for (const deal of response.data.data) {
db.get('deals').push(deal)
}
db.save() // Save changes to temp DB
resolve(response.data.data) // Resolve Promise with the data from the successful call
}
})
.catch((err) => {
console.log(chalk.red(err))
reject(err)
})
})
}
您的 more_items_in_collection 案例永远无法兑现承诺。它只是创建一个新的,然后什么也不做。
此外,使用 new Promise
会使代码变得比需要的更复杂。 Axios 已经 return 是一个承诺,所以没有必要明确地创建一个新的。调用 .then
将自动创建一个新的承诺,它解析为您在回调中 return 的任何值。
const queryPipeDrive = (start) => {
// API CALL
return axios({
method: "GET",
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start,
},
})
// THEN DO THIS
.then((response) => {
// IF there are more items in collection on additional pages, iterate through the pages
if (response.data.additional_data.pagination.more_items_in_collection) {
// Add all deals on page to the container
for (const deal of response.data.data) {
db.get("deals").push(deal); // Push deal data to the StormDB File
}
console.log(
chalk.cyan(`${response.data.additional_data.pagination.next_start}`)
);
// Function loop created. We will loop UNTIL the 'more_items_in_collection' prop is false, then we'll resolve the promise.
return queryPipeDrive(
response.data.additional_data.pagination.next_start
);
} else {
// Add all deals on this page to the reponse container
for (const deal of response.data.data) {
db.get("deals").push(deal);
}
db.save(); // Save changes to temp DB
return response.data.data;
}
})
.catch((err) => {
console.log(chalk.red(err));
throw err;
});
};
除了已接受的答案。
你会考虑在 await 中使用这个异步函数吗?这样,你就调用了main()
.
const main = async start => {
const res = await queryPipeDrive(start);
if (res.isMoreItems === true) {
await main(res.nextStart);
}
};
async function queryPipeDrive(start) {
const response = await axios({
method: "GET",
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start,
},
});
for (const deal of response.data.data) {
db.get("deals").push(deal);
}
if (response.data.additional_data.pagination.more_items_in_collection) {
console.log(
chalk.cyan(`${response.data.additional_data.pagination.next_start}`)
);
return {
isMoreItems: true,
nextStart: response.data.additional_data.pagination.next_start,
};
} else {
db.save(); // Save changes to temp DB
return {
isMoreItems: false,
};
}
}