我正在编写一个在节点环境中的cron作业上运行的进程。
该进程从两个外部服务中提取两个用户列表,写入文件,并进行一些比较。
用户的一个来源是Discourse论坛,不幸的是,为了获得完整的用户列表,我们必须获取多个trust_level
列表并将它们连接起来。
我使用各种嵌套的promise和Promise.all
来构建它。但是,下面的函数在then
和forumList.json
存在之前过早地调用databaseList.json
回调...我在这里做错了什么?
import superagent from 'superagent'
import { writeFileSync } from 'fs'
export default function fetchData() {
const process = []
const databaseFetch = new Promise((resolve, reject) => {
superagent.get('https://our-api.com/api/1/databases/our-db/collections/users')
.end((error, response) => {
if (error) {
reject(error)
} else {
writeFileSync('temp/databaseList.json', JSON.stringify(response.body))
resolve()
}
})
})
const forumFetch = new Promise((resolve, reject) => {
// For reference, see https://meta.discourse.org/t/how-do-i-get-a-list-of-all-users-from-the-api/24261/8
// We have to do this because of the way the discourse API is built
const discourseApiList = [
'trust_level_0',
'trust_level_1',
'trust_level_2',
'trust_level_3',
'trust_level_4',
]
let forumList = []
const discoursePromises = discourseApiList.map((trustLevel) => {
return new Promise((resolveInner, rejectInner) => {
superagent.get(`https://our-website.com/forum/groups/${trustLevel}/members.json`)
.end((error, response) => {
if (error) {
rejectInner(error)
reject()
} else {
forumList = forumList.concat(response.body.members)
resolveInner()
}
})
})
})
Promise.all(discoursePromises).then(() => {
writeFileSync('temp/forumList.json', JSON.stringify(forumList))
resolve()
})
})
process.push(databaseFetch)
process.push(forumFetch)
return Promise.all(process)
}
答案 0 :(得分:1)
承诺代码对我来说很好,问题必须在其他地方。
function fetchData() {
const process = []
const databaseFetch = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('resolving databaseFetch');
resolve();
}, Math.round(Math.random() * 10000));
})
const forumFetch = new Promise((resolve, reject) => {
const discourseApiList = [
'trust_level_0',
'trust_level_1',
'trust_level_2',
'trust_level_3',
'trust_level_4',
]
let forumList = []
const discoursePromises = discourseApiList.map((trustLevel) => {
return new Promise((resolveInner, rejectInner) => {
setTimeout(function() {
console.log('resolving ' + trustLevel);
resolveInner();
}, Math.round(Math.random() * 10000));
})
})
Promise.all(discoursePromises).then(() => {
setTimeout(function() {
console.log('resolving discoursePromises');
resolve();
}, Math.round(Math.random() * 1000));
})
})
process.push(databaseFetch)
process.push(forumFetch)
return Promise.all(process)
}
fetchData().then(() => console.log('finished!'));
答案 1 :(得分:0)
你永远不应该嵌套Promise
,因为它们的唯一目的是创建线性代码。我建议采取这种方式:
1-创建discoursePromises
并使用Promise.all
2-然后,创建forumFetch
和databaseFetch
并使用Promise.all
解析它们
我认为您可能会发现有趣的async,这是一个很棒的流量控制库。特别要看parallel
。
希望这会有所帮助。
答案 2 :(得分:-1)
识别承诺:
const promise1Fun = () => {
return new Promise((resolve, reject) => {
//do stuff
})
}
const promise2Fun = () => {
return new Promise((resolve, reject) => {
//do stuff
})
}
链接承诺:
promise1Fun.then(promise2Fun).catch((err) => console.error(err))