首页 > 解决方案 > 在 for 循环中使用 Promise

问题描述

我正在尝试遍历一系列日期以返回每个日期的热门歌曲。所以我有一个 for 循环。在这个 for 循环中,调用了一个函数来查看我的数据库中的热门歌曲。因此,我将它包装在一个 Promise 中,以便它支持 for 循环,但这种方法似乎也不起作用。有人可以解释一个更好的方法来解决这个问题。

app.post('/getDate', function (req, res) {
      this.tracks = [];
      let until = new Date(req.body.dateToOutput);
      for (var d = new Date(req.body.dateFromOutput); d <= until; d.setDate(d.getDate() + 1)) {
            date = d.toLocaleDateString('en-US', { timeZone: 'UTC' });
            console.log('date', date);
            new Promise(function (resolve, reject) {
                  getDate(date).then(() => {
                        resolve();
                  })
            });
      }
      console.log(this.tracks);
});
function getDate(date) {
      return new Promise(function (resolve, reject) {
            Track.find({ Date: date }, function (err, track) {
                  if (!err) {
                        console.log(track);
                        this.tracks.push(track);
                        resolve();
                  }
                  else {
                        reject();
                  }
            }).sort({ Streams: -1 }).limit(1);
      });
}

标签: javascriptexpressmongoosepromise

解决方案


我认为诺言没有被执行,而且我认为您在 getDate 函数中指向一个未定义的对象,并且 for 循环不会等待解决或拒绝的诺言。看到这个:

new Promise(function (resolve, reject) {
    getDate(date).then(() => {
        resolve();
    })
});

你正在创建一个新的承诺,但你从未执行过这个承诺。

同样在函数中,getDate您指向的对象在他的上下文中不存在:

this.tracks.push(track);

这会给您带来一些错误,因为this.tracks不是getDate函数的一部分,而是该方法调用的匿名函数的一部分app.post

this.tracks因此,您必须返回轨道本身,而不是直接推入:

if (!err) {
    console.log(track);
    resolve(track);
}

那么你应该使用 async - await 来强制循环在承诺处暂停,直到这个被解决或拒绝,所以你的匿名函数现在应该是一个异步匿名函数才能使用 await,你也不需要另一个承诺中的承诺包装,我的意思是你不需要这个:

new Promise(function (resolve, reject) {
    getDate(date).then(() => {
        resolve();
    })
});

你只需要这个:

getDate(date).then(() => {
   resolve();
})

因为 getDate() 函数本身返回一个承诺。

所以这就是你的代码在进行所有这些更改后的样子:

const response = app.post('/getDate', async function (req, res) {
      this.tracks = [];

      let until = new Date(req.body.dateToOutput);
      for (var d = new Date(req.body.dateFromOutput); d <= until; d.setDate(d.getDate() + 1)) {
            date = d.toLocaleDateString('en-US', { timeZone: 'UTC' });
            console.log('date', date);
            const ctrack = await getDate(date);
            this.tracks.push(ctrack);
      }

      console.log(this.tracks);
      return this.tracks;
});

function getDate(date) {
      return new Promise(function (resolve, reject) {
            Track.find({ Date: date }, function (err, track) {
                  if (!err) {
                        console.log(track);
                        resolve(track);
                  }
                  else {
                        reject();
                  }
            }).sort({ Streams: -1 }).limit(1);
      });
}

现在您将响应作为一个承诺,因为异步函数返回一个承诺......然后您可以捕获它并使用响应:

response.then(trackList =>{
   console.log(trackList);
}).catch(()=>{
   console.error("something went wrong...!");
})

推荐阅读