javascript - 如何访问 Promise 的值?

标签 javascript reactjs firebase asynchronous react-hooks

我正在编写一个由两个数据库构建的评论系统:一个包含评论者的文本和 ID,然后用于访问第二个数据库以检索并动态显示发布者的个人资料信息(pfp 和显示名称)对于他们提交的每条评论。

useEffect() Hook 内的函数返回 Promises 数组。我一直在试图找出访问这些 Promise 中的值的方法,但到目前为止还没有成功。我知道 .then() 专门用于此目的,但我不明白在这种情况下如何以及在何处正确应用它。

import React, { useEffect, useState, Fragment } from 'react'
import firebase from './firebase'

export const Comments = () => {

    const [cred, setCred] = useState('')
    const [comment, setComment] = useState('')
    const [allComments, setAllComments] = useState(null)

    useEffect(() => {

// grab the database containing poster ID 
// & text of each single comment by it's name and then map over it

        firebase.getData('text&ID').onSnapshot(snapshot => setAllComments([...snapshot.docs.map(async (doc) => {

// using the poster ID, 
// access the 'users' DB that contains the avatar & name fields

            let comment = doc.data().content
            let poster = await firebase.getData('users').doc(doc.data().posterID).get()
            let name = poster.data().name
            let avatar = poster.data().avatar

// returning an object of all the data we want to display for each comment

            return ({
                name: name,
                avatar: avatar,
                comment: comment
            })
        })]))

// if user exists, set state to their credentials

        firebase.isInitialized().then(val => setCred(val))       
    }, [])

    return allComments && <Fragment>

// submit the comment to the text&DB collection with text, poster ID and text 

        {cred && <form onSubmit={(e) => {
            e.preventDefault()
            firebase.addComment('text&ID', cred.uid, comment).then(console.log('comment sent!')).then(setComment(''))
        }}>
            <input
                type="text"
                value={comment}
                name="text"
                placeholder="comment..."
                onChange={e => { setComment(e.target.value) }}
                required
            />
            <br />
            <button >Post</button>
        </form>}
        <ul>

// the plan was to map over allComments 
// and return an <li> with all the display info
// but logging to console displays THE array of Promises
// that I want to access

            {console.log(allComments)}
        </ul>
    </Fragment>
}

非常欢迎任何和所有的意见。

这是 console.log 输出:

[Promise]
   0: Promise
      __proto__: Promise
         [[PromiseStatus]]: "resolved"
         [[PromiseValue]]: Object
            avatar: "https://i.imgur.com/v4ImnVE.jpg"
            comment: "no halo"
            name: "polnareff"
         __proto__: Object
      length: 1
      __proto__: Array(0)

最佳答案

async function表示一个异步函数,实际上返回一个Promise,以便在函数内的所有代码都已执行时收到通知。

因此,在您的代码中 [...snapshot.docs.map(async ...)] 将返回一个 Promise 数组。顺便说一句,您不需要使用解构运算符 ...,您可以直接使用 snapshot.docs.map 它将返回一个新数组。

您可以使用Promise.all等到所有 promise 都得到解决,然后更新状态变量allComments

这是您的效果代码:

useEffect(() => {

  firebase.getData('text&ID').onSnapshot(snapshot => {
    const commentPromises = snapshot.docs.map(async (doc) => {
      const {posterId} = doc.data();
      const poster = await firebase.getData('users').doc(posterID).get();
      const {avatar, name, content: comment} = poster.data()

      return {name, avatar, comment};
    });

    Promise.all(commentPromises)
      .then(setAllComments)
      .catch(...);
  });

  firebase.isInitialized()
    .then(val => setCred(val))
    .catch(...);
});

关于javascript - 如何访问 Promise 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58670639/

相关文章:

javascript - 将utc时间转换为特定格式的本地时间

javascript - 如何以 HTML 表单提交下拉选择?

html - React - svg 内的 html 标签

css - Material-UI:如何防止 Grid 元素出现在下一行?

Firebase 规则 : using parent values to validate?

firebase - Flutter - firebase_auth updateProfile 方法不起作用

javascript - three.js 灯没有在 chrome 上的 Apache 服务器下呈现

javascript - 如何在rails中将远程功能与check_box_tag一起使用

javascript - 在另一个 CSSTransition 中嵌套 CSSTransitions?

javascript - 当 firebase 更新时,React 组件不会更新