我正在尝试通过 soundcloud API 下载轨道,然后在下载了不确定数量的轨道后启动回调。当我运行下面的代码时,我看到“全部完成”在其他任何事情之前都被控制台记录,即使我打算将其作为最后一件事......我做错了什么?
// Deps
import fs from 'fs'
import SC from 'node-soundcloud'
import request from 'request'
// Write mp3 function
function writeMP3(track) {
return new Promise((resolve, reject) => {
console.log('Starting download: ', track.title)
request.get(track.download_url)
.on('error', err => {
// reject('Download error: ', err)
})
.on('finish', () => {
() => resolve('Download complete')
})
.pipe(fs.createWriteStream(`./data/temp/${track.title}_${track.user.username}.mp3`))
})
}
async function asyncTrackFetch(track) {
return await writeMP3(track)
}
// Array of promises to callback upon
const trackActions = []
SC.init({
id: 'MY_ID',
secret: 'MY_SECRET'
})
SC.get('/tracks', (err, tracks) => {
if (err) {
throw new Error(err)
} else {
console.log('Tracks fetched: ', tracks.length)
tracks.map(track => {
if (track.downloadable) {
console.log('downloadable')
trackActions.push(asyncTrackFetch(track))
}
})
}
})
// Perform requests async
Promise.all(trackActions).then(() => {
console.log('All done')
console.log(fs.readdirSync('./data/temp'))
})
最佳答案
Promise.all(trackActions)
等待 trackActions
中的所有 Promise,但在您进行调用时 trackActions
为空。您仅在调用 SC.get
回调后将 Promise 添加到数组中。
尝试将 Promise.all...
block 放入 SC.get
回调中,如下所示:
SC.get('/tracks', (err, tracks) => {
if (err) {
throw new Error(err)
} else {
console.log('Tracks fetched: ', tracks.length)
tracks.map(track => {
if (track.downloadable) {
console.log('downloadable')
trackActions.push(asyncTrackFetch(track))
}
})
Promise.all(trackActions).then(() => {
console.log('All done')
console.log(fs.readdirSync('./data/temp'))
})
}
})
还值得一提的是,您的行 throw new Error(err)
将使程序崩溃,因为没有地方可以捕获该错误。
正如 Antonio Val 提到的,有更好的方法可以做到这一点。如果您 promise 使用 node-soundcloud 库,那么代码的最后一部分可能如下所示:
SC.get('/tracks').then(tracks => {
// No need for trackedActions array.
return Promise.all(tracks.filter(track => track.downloadable)
.map(track => asyncTrackFetch(track)))
}).then(fetchedTracks => {
console.log('All done fetching tracks', fetchedTracks)
}).catch(err => {
// Handle error.
})
或者在 async function 内,
try {
const tracks = await SC.get('/tracks')
const fetchPromises = tracks
.filter(track => track.downloadable)
.map(track => asyncTrackFetch(track))
const fetchedTracks = await Promise.all(fetchPromises)
console('All done fetching tracks.', fetchedTracks)
} catch (err) {
// Handle error
}
关于node.js - 使用 async wait 有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42749711/