【问题标题】:Using Promises within for loop在 for 循环中使用 Promise
【发布时间】:2020-07-27 21:36:21
【问题描述】:

我正在尝试遍历一系列日期以返回每个日期的热门歌曲。所以我有一个 for 循环。在这个 for 循环中,调用了一个函数来查看我的数据库中的热门歌曲。因此,我将它包装在一个承诺中,以便它能够支撑 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);
      });
}

【问题讨论】:

  • 我认为您的问题已经得到解答,请查看:stackoverflow.com/questions/40328932/…
  • 另外你正在使用一个非常奇怪的 for 循环,它可能会中断或抛出一堆错误,为什么不使用数值?,我认为如果你不修复循环,我的答案将不起作用.
  • 啊,我忘记了另一件事,在您的 getDate 函数中,您有 .sort({Streams: -1}).limit(1),它永远不会反映在您的代码中,因为在Track.find 方法被执行,但我怀疑你的 Track.find 方法的返回总是未定义的,如果不是未定义的,你将它应用于不会在承诺中返回的东西,所以你正在做的操作不会反映在你的承诺中,就像创建一个变量而不使用它。

标签: javascript express mongoose promise


【解决方案1】:

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

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 来强制循环在 promise 处暂停,直到它被解决或拒绝,所以你的匿名函数现在应该是一个异步匿名函数,以便使用 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);
      });
}

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-13
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 2018-06-09
    相关资源
    最近更新 更多