node.js - 使用 async wait 有什么问题吗?

标签 node.js asynchronous async-await es6-promise ecmascript-2017

我正在尝试通过 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/

相关文章:

node.js - 使用 smbget 在 Node js 中从 Windows 转移到 Linux

c# - 如何在循环中等待操作响应 C#

node.js - 如何使用 grunt-debian-package 填充源包?

JavaScript ES2017 : Nested async await in a class

java - 如何在 Vert.x 中实现自定义异步操作?

c# - 纤程与异步等待

c#-4.0 - 错误 : The operation was canceled

javascript - 如果我定义了一个异步函数并在主体中使用了await,那么在调用该函数时是否需要使用await?

javascript - 如何在 Node/Javascript 中丢弃数字的小数部分

javascript - 如何将用户输入打印到控制台?