【问题标题】:Trying to get API's Promise resolved using map()尝试使用 map() 解决 API 的 Promise
【发布时间】:2019-10-10 03:14:55
【问题描述】:

更新:已解决!

唯一需要的更改是将 API 调用的 await 设置为 return,然后返回带有图像名称和 ID 的地图。仍在尝试将地图转换为数组,但这篇文章的这个问题已经解决。这是新的打印输出:

1 face detected from image Family1-Son1.jpg with ID 98091e1e-bc8d-4c93-a850-a115684a6e6e
Family1-Son1.jpg
1 face detected from image Family1-Dad3.jpg with ID f94360f5-feb3-4d14-816f-7d854fc0b34c
Family1-Dad3.jpg
[ { '0': 'F',
    '1': 'a',
    '2': 'm',
    '3': 'i',
    '4': 'l',
    '5': 'y',
    '6': '1',
    '7': '-',
    '8': 'D',
    '9': 'a',
    '10': 'd',
    '11': '3',
    '12': '.',
    '13': 'j',
    '14': 'p',
    '15': 'g',
    id: 'f94360f5-feb3-4d14-816f-7d854fc0b34c' },
  { '0': 'F',
    '1': 'a',
    '2': 'm',
    '3': 'i',
    '4': 'l',
    '5': 'y',
    '6': '1',
    '7': '-',
    '8': 'S',
    '9': 'o',
    '10': 'n',
    '11': '1',
    '12': '.',
    '13': 'j',
    '14': 'p',
    '15': 'g',
    id: '98091e1e-bc8d-4c93-a850-a115684a6e6e' } ]
[ <2 empty items> ]
[]

我在这里尝试了许多不同的方法,但无法让它们起作用。这是我来的最近的一个。我正在尝试调用 API,但在数组中的每个项目上。我不能在常规循环中执行此操作,原因有很多。所以有人说使用 array.map() 函数而不是循环。我做到了这一点:

const IMAGE_BASE_URL = 'https://csdx.blob.core.windows.net/resources/Face/Images/'
let sourceImageFileNames = ['Family1-Dad3.jpg', 'Family1-Son1.jpg']

// Detect faces in the source image array, then get their IDs
let sourcefaceMap = await Promise.all(sourceImageFileNames.map(async (imageName) => {
   // Returns a Promise<DetectedFace[]>
    await client.face.detectWithUrl(IMAGE_BASE_URL + imageName)
        .then((faces) => {
            console.log(`${faces.length} face detected from image ${imageName} with ID ${faces[0].faceId}`)
            let id = faces[0].faceId
            return { ...imageName, id } 
        }).catch((err) => {
            console.log(`No face detected in: ${sourceImageFileNames[0]}.`)
            throw err;
        })
}))

let values = Object.values(sourcefaceMap)
console.log(values)

// Create an array to store the source face IDs
var sourceFaceIds = new Array(sourceImageFileNames.length)
console.log(sourceFaceIds)
let ids = sourceFaceIds.filter((id)=> {
    return id != null;
})

console.log(ids)

调试时这些值似乎存在,但是当我尝试返回地图时,它打印为未定义。即使地图确实完成了循环获取每个 id 的工作(如前两个打印语句所示)。 这是我的打印输出:

VERIFY
1 face(s) detected from image Family1-Dad3.jpg with ID f94360f5-feb3-4d14-816f-7d854fc0b34c
1 face(s) detected from image Family1-Son1.jpg with ID 98091e1e-bc8d-4c93-a850-a115684a6e6e
[ undefined, undefined ]
[ <2 empty items> ]
[ <2 empty items> ]

这是一个具有值的 id 的屏幕截图,当我在 return 语句中将鼠标悬停在它上面时:

基本上,我正在尝试使用 URL 图像进行 API 调用,然后 API 会将 ID 与图像中的每个人脸相关联。我需要 API 调用来返回所有这些 ID。在这种情况下,它只有 2 个 ID。我该怎么做呢?在我的代码的最后,我只需要这些 ID 的数组。就这样。谢谢。

【问题讨论】:

  • 你能编辑你的问题吗,让我知道你最后需要什么输出
  • 感谢@NarendraChouhan,它在最后一段中说我需要一个 ID 数组。因此,如果我打印sourceFaceIds,它将打印一个数组。我需要一组 ID 用于稍后出现的另一个 API 调用(未显示,因为与此问题无关)。这很奇怪,因为这段代码在这里为其他人工作,不知道为什么 id 变量没有在 return 语句中使用。
  • @NarendraChouhan 我稍微编辑了代码,修复了一些不相关的错误,并添加了一些 cmets 以尝试更清楚地了解整个架构在做什么。有时间的话重新看一下,谢谢。
  • new Array(sourceImageFileNames.length) 应该完成什么?我怀疑 this does 你的期望。
  • @Bergi 哇,感谢您指出这一点。我习惯了其他语言,Node 有很多回调,它们让我很头疼。我只是想转换地图的值(实际上只是键/值对的最后一个值——ID)并将它们存储到一个数组中。所以最后我有一个包含两个 ID 的数组,在这种情况下。在这种情况下,是否有更好的方法来实例化数组?我想我可以只获取最后一个地图值并用它们定义一个新数组(而不是创建一个空数组开始)。我会试试这个!谢谢!

标签: node.js promise async-await


【解决方案1】:

你的map 回调没有return 任何东西,它只是等待。使用

const values = await Promise.all(sourceImageFileNames.map(imageName => {
    // now *really* returns a Promise<DetectedFace[]>
    return client.face.detectWithUrl(IMAGE_BASE_URL + imageName)
        .then(faces => {
            console.log(`${faces.length} face detected from image ${imageName} with ID ${faces[0].faceId}`)
            let id = faces[0].faceId
            return { imageName, id } 
        }).catch((err) => {
            console.log(`No face detected in: ${sourceImageFileNames[0]}.`)
            throw err;
        })
}));
console.log(values);

我也很确定您不想将 imageName 字符串传播到对象中,并且不需要在数组上调用 Object.values 来将其值作为数组获取。

【讨论】:

  • 这完全有效,谢谢!我从没想过要归还整件事。 :D 现在我只需要弄清楚如何将地图结果转换为数组,但这是另一个问题。再次感谢!我将更新代码(添加而不是替换)以显示新的打印输出。
  • @Azurespot 地图结果一个数组。无需转换。
  • 谢谢,呃。经过多次试验和错误,我发现这是真的。一个包含 2 个地图对象的数组,对吧?我一直试图从对象中获取密钥id,但它不允许我说TypeError: sourceFaceMap[0].get is not a function 那么数组中的对象不是映射吗?真的很困惑,因为当我打印出来时,它有键值对。这是我的代码:console.log(sourceFaceMap) console.log(sourceFaceMap[0].get('id'))
  • 终于,终于明白了。它是字典而不是地图。男孩,我不太了解JS,哈哈。这得到了我一直想要的 id:console.log(sourceFaceMap[0]['id']) 再次感谢你,真的是你救了我的工作。 :)
  • 是的,返回的{ imageName, id }{"imageName": imageName, "id": id} 的缩写)是一个普通对象,而不是地图。如果您只想获取 id,则可以将对象替换为 return id;
【解决方案2】:

我认为您在let id = response.faceId 在线遇到的问题。

id 正在从 response.faceId 获取其值,请检查响应对象中是否存在 faceId 属性。如果它存在,那么代码将按您的预期工作。

【讨论】:

  • 感谢@iAmADeveloper,我能够为我的id 变量获取值。我稍微编辑了代码,我错过了 API 承诺的解析,因为这是它返回的内容,但是随后在整个 map() 中添加了一个 Promise,也许这是矫枉过正?只是不确定如何循环遍历数组并在每个数组项(源图像)上调用 API。我的新代码是否更清楚问题?谢谢。
猜你喜欢
  • 1970-01-01
  • 2017-11-28
  • 2017-10-13
  • 2019-08-31
  • 2012-09-07
  • 2020-10-15
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多