JS return 不等待 await
JS return doesn't wait for await
我正在尝试使用异步等待。
我的应用是这样启动的
axios.get(`${ROOT_URL}/ccidxann.php`)
.catch(err => console.error('axios error get', err))
.then(async res => {
const html = res.data
const jobList = await getJobList(html)
console.log(' after each jobList', jobList)
// jsonfile.writeFileSync('jobs.json', jobList, { flag: 'a' })
})
.catch(err => console.error(err))
问题是 jobList
总是作为空数组返回。
这是 getJobList
函数
async function getJobList (html) {
const jobList = []
const dom = new JSDOM(html)
const { window } = dom
const $ = require('jquery')(window)
const jobsInDom = $('table').first().find('td > a')
// AWAIT HERE
await jobsInDom.each(async function (index, jobElem) {
const name = $(jobElem).text()
const url = $(jobElem).attr('href')
// Another AWAIT HERE
const jobDetailsHTML = await getJobDetailsHTML(`${ROOT_URL}/${url}`)
.catch(err => console.error('getJobDetailsHTML err', err))
const domDetails = new JSDOM(jobDetailsHTML)
const { window: windowDetails } = domDetails
const $details = require('jquery')(windowDetails)
const jobDetailsHTMLBody = $details('body').prop('outerHTML')
jobList.push({
_id: url,
name,
detailsHTML: jobDetailsHTMLBody
})
console.log('in each jobList', jobList)
}) //each
return jobList
}
如你所见,我把async
关键字放在了它的前面,
并且我在 each
的回调中放入了 async
关键字
并将await
放在所有异步操作的前面。
each
回调中的console.log
打印出填充了值的数组
但似乎 return
在 each
之前起作用
即使前面有 await
关键字。
这里还有 getJobDetailsHTML
以防万一。这是一个简单的功能,似乎工作得很好
async function getJobDetailsHTML (url) {
// ANOTHER AWAIT HERE
return await axios.get(url).data
}
我认为jobsInDom.each
是同步函数,所以把await放在前面不会给你想要的效果。因此,您需要以某种方式获得承诺,该承诺会在所有作业的处理完成后得到解决,如下所示:
// handles one element and returns promise
const jobHandler = async jobElem => {
const name = $(jobElem).text()
const url = $(jobElem).attr('href')
const jobDetailsHTML = await getJobDetailsHTML(`${ROOT_URL}/${url}`)
.catch(err => console.error('getJobDetailsHTML err', err))
const domDetails = new JSDOM(jobDetailsHTML)
const { window: windowDetails } = domDetails
const $details = require('jquery')(windowDetails)
const jobDetailsHTMLBody = $details('body').prop('outerHTML')
jobList.push({
_id: url,
name,
detailsHTML: jobDetailsHTMLBody
})
console.log('in each jobList', jobList)
}
const promises = [];
// start processing of each element
jobsInDom.each((index, jobElem) => promises.push(jobHandler(jobElem));
// wait for processing of all job elements
await Promise.all(promises);
我正在尝试使用异步等待。
我的应用是这样启动的
axios.get(`${ROOT_URL}/ccidxann.php`)
.catch(err => console.error('axios error get', err))
.then(async res => {
const html = res.data
const jobList = await getJobList(html)
console.log(' after each jobList', jobList)
// jsonfile.writeFileSync('jobs.json', jobList, { flag: 'a' })
})
.catch(err => console.error(err))
问题是 jobList
总是作为空数组返回。
这是 getJobList
函数
async function getJobList (html) {
const jobList = []
const dom = new JSDOM(html)
const { window } = dom
const $ = require('jquery')(window)
const jobsInDom = $('table').first().find('td > a')
// AWAIT HERE
await jobsInDom.each(async function (index, jobElem) {
const name = $(jobElem).text()
const url = $(jobElem).attr('href')
// Another AWAIT HERE
const jobDetailsHTML = await getJobDetailsHTML(`${ROOT_URL}/${url}`)
.catch(err => console.error('getJobDetailsHTML err', err))
const domDetails = new JSDOM(jobDetailsHTML)
const { window: windowDetails } = domDetails
const $details = require('jquery')(windowDetails)
const jobDetailsHTMLBody = $details('body').prop('outerHTML')
jobList.push({
_id: url,
name,
detailsHTML: jobDetailsHTMLBody
})
console.log('in each jobList', jobList)
}) //each
return jobList
}
如你所见,我把async
关键字放在了它的前面,
并且我在 each
async
关键字
并将await
放在所有异步操作的前面。
each
回调中的console.log
打印出填充了值的数组
但似乎 return
在 each
即使前面有 await
关键字。
这里还有 getJobDetailsHTML
以防万一。这是一个简单的功能,似乎工作得很好
async function getJobDetailsHTML (url) {
// ANOTHER AWAIT HERE
return await axios.get(url).data
}
我认为jobsInDom.each
是同步函数,所以把await放在前面不会给你想要的效果。因此,您需要以某种方式获得承诺,该承诺会在所有作业的处理完成后得到解决,如下所示:
// handles one element and returns promise
const jobHandler = async jobElem => {
const name = $(jobElem).text()
const url = $(jobElem).attr('href')
const jobDetailsHTML = await getJobDetailsHTML(`${ROOT_URL}/${url}`)
.catch(err => console.error('getJobDetailsHTML err', err))
const domDetails = new JSDOM(jobDetailsHTML)
const { window: windowDetails } = domDetails
const $details = require('jquery')(windowDetails)
const jobDetailsHTMLBody = $details('body').prop('outerHTML')
jobList.push({
_id: url,
name,
detailsHTML: jobDetailsHTMLBody
})
console.log('in each jobList', jobList)
}
const promises = [];
// start processing of each element
jobsInDom.each((index, jobElem) => promises.push(jobHandler(jobElem));
// wait for processing of all job elements
await Promise.all(promises);