javascript - 在映射数组时调用 Promise

标签 javascript

在 map 内使用 Promise 时,我遇到了一些奇怪的行为。

这本身并不是一个问题,但我想了解发生了什么。

let books = [
  {Name: "Moby Dick",
  AuthorId: 1
  },
  {Name: "The Great Gatsby",
  AuthorId: 2}
]

let authors = [
  {AuthorId: 1,
  Name: "Herman Melville"
  },
  {AuthorId: 2,
  Name: "F. Scott Fitzgerald"
  }
]

const getAuthorName = (AuthorId) => {
  return new Promise((resolve, reject) => {
     setTimeout(() => {
     resolve(authors.find((author) => {
        return author.AuthorId === AuthorId
        }).Name)
     }, 1000

  })
}
let responseArray = []
let promises = books.map((book) => (
  getAuthorName(book.AuthorId).then((res) => {
    responseArray.push({
      ...book,
      AuthorName: res
    })
  })
))

setTimeout(() => console.log(responseArray), 500)

//I would expect to have to do this:
//Promise.all(promises).then((res) => console.log(res))

我希望

setTimeout(() => console.log(responseArray), 5000) 

记录一个空字符串,因为 Promise 数组尚未通过 Promise.all 运行,但看起来即使映射应该只是返回一个 Promise 数组,但它实际上正在运行 Promise。这是为什么?

编辑

我已经编辑了 getAuthor promise ,在决定进一步详细说明之前稍等一下,因为这不是我想要表达的重点。

我希望映射一个数组,以返回一个新数组,其中包含映射中返回的任何内容。例如,如果我这样做

let arrayOfPromises = books.map((book) => {
   return getAuthor(book.AuthorId)
}

我希望 arrayOfPromises 是 getAuthor promise 的数组。

但是,当我在返回的 Promise 末尾抛出 .then() 时,.then() 中的代码似乎正在计算。

如果我这样做

let promises = books.map((book) => {
   return getAuthor(book.AuthorId).then((res) => {
      console.log(res)
   })
}

在控制台中,我将看到“Herman Merville”和“F. Scott Fitzgerald”,在 Promise var 中,我将看到一系列 Promise。

虽然我认为每个 getAuthor 的 .then 只会在我调用 Promise.all(promises) 时进行评估,因为 getAutor promise 会在 map 内返回。我在这里理解有问题吗?

最佳答案

这是因为您的 Promise 中的代码不是异步的,因此它会立即解析,因为没有什么可等待的。

要对此进行扩展,您所做的与

相同
const getAuthorName = (AuthorId) => {
  return Promise.resolve(authors.find((author) => {
    return author.AuthorId === AuthorId
  }).Name)
}

它将允许您在函数上链接 then 语法,但这也意味着 then 将在函数调用后直接执行。

编辑

根据您的编辑,这里还有一些内容。

您已使用 setTimeout 将方法修改为异步。这意味着 map 现在按照您的预期返回一组 promise 。

但是您的代码还有另一个问题,您还将 console.log 封装在 setTimeout 中,该计时器具有更大的计时器!

为了更好地了解这里发生的事情,我强烈建议您观看 this video .

但是,本着 StackOverflow 的精神,我将在此处添加一些书面解释。

您首先创建一个 Promise 数组,在创建后大约 1 秒后执行回调(它们不会等待 map 结束)。

一旦完成,它们就会进入浏览器的事件循环。基本上,它是主线程释放后浏览器将立即处理的一堆事件。

因此,在创建后 1 秒,promise 将解析,并将其回调放在此事件循环上。

现在,当您运行 console.log 时会发生什么。

如果您没有将其放入自己的 setTimeout 中,它将打印一个空数组。

如果 setTimeout 为 500 毫秒怎么办?在这里,我们可以放心地假设 map 将花费不到 500 毫秒的时间来完成并启动新的 setTimeout,因此 console.log 将到达 <首先是事件循环,然后再次打印一个空数组。

5秒怎么样?在到达 console.log 之前,两个 setTimeouts 都会结束,因此您将打印一个已填充的数组。

我做了一个jsfiddle如果您想亲自尝试一下。

我希望这有助于澄清问题。

关于javascript - 在映射数组时调用 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57419751/

相关文章:

javascript - Highcharts:双面传奇

javascript - 如何判断一个 DOM 元素是否显示?

javascript - 检测智能 watch 何时访问网页

javascript - 检测所选元素是否是右键单击的 anchor

JavaScript 替换问题

javascript - 为什么我的 event.soptPropagation 在 React 中不起作用?

javascript - WebRTC 传输高音频流采样率

javascript - 在 Android 中使用 Jquery Mobile 和 Phonegap 来触摸移动和滚动内容

javascript - 需要通过 JavaScript 解析 XML 数据的帮助

javascript - Angular JS ng-包含