简体   繁体   English

使用 Promise 进行顺序渲染

[英]Sequential Rendering Using Promises

I have a view whereby I want to present 10 items by date sequentially.我有一个观点,我想按日期顺序呈现 10 个项目。 This data (the 10 items), is fetched from an API and is already sorted by date.此数据(10 项)是从 API 中获取的,并且已经按日期排序。 A quick sample:快速示例:

{
  "meta": { ... },
  "data": [
    {
      "id": 4891,
      "date": "February 23rd, 2021",
      "photo": "",
    },
    {
      "id": 3126,
      "date": "February 22nd, 2021",
      "photo": "",
    },
    {
      "id": 7895,
      "date": "February 21st, 2021",
      "photo": "123-sesame-st-bd088111.jpg",
    }
  ]
}

I have included a photo to help visualize.我附上了一张照片来帮助形象化。 In some scenarios, such as the cards with the kittens, I have known photo assets from the initial data load.在某些情况下,例如带有小猫的卡片,我从初始数据加载中就知道了照片资产。 Scenarios where I do not have a known photo asset, such as the cards with the houses, I fetch those image assets from a secondary API call.在我没有已知照片资产(例如带有房屋的卡片)的场景中,我从辅助 API 调用中获取这些图像资产。

在此处输入图像描述

I am attempting to rely on promises to maintain the order when rendering these items to the view.在将这些项目呈现到视图时,我试图依靠承诺来维持秩序。 Noting the dates at the bottom of each card, read left to right, this is not working.注意每张卡片底部的日期,从左到右阅读,这是行不通的。 How can I maintain the rendered order of each item, as is returned from the initial data load?如何维护每个项目的呈现顺序,就像从初始数据加载返回的那样?

Here's my current code with some things removed to better focus on the core logic:这是我当前的代码,删除了一些内容以更好地关注核心逻辑:

ready(() => {

    const cards = document.getElementById("cards")

    function fetchPhoto(id) {
        return fetch(`https://api.com/photo/${id}`)
            .then((res) => { return res.json() })
            .then((res) => {
                return res.photo
            })
    }

    function renderCard(item, photo) {
        let postCard = document.createElement('div')
        postCard.innerHTML = `<div>...${photo}...</div>`
        return postCard
    }

    function createCard(item) {
        if (item.photo) {
            return new Promise((resolve, reject) => {
                resolve(renderCard(item, item.photo))
            });
        }
        return fetchPhoto(item.id).then(photo => {
            return renderCard(item, photo)
        });
    }

    function loadRecent() {
        fetch('https://api.com/items?limit=10')
            .then((res) => { return res.json() })
            .then((res) => {
                res.data.forEach(item => {
                    createCard(item).then(card => {
                        cards.appendChild(card)
                    })
                })
            })
    }

    loadRecent()

}

I have elected to take Thomas' advice, and render the cards first, then load images later.我选择接受 Thomas 的建议,先渲染卡片,然后再加载图像。

ready(() => {

    const cards = document.getElementById("cards")

    function fetchPhoto(id) {
        fetch(`https://api.com/photo/${id}`)
            .then((res) => { return res.json() })
            .then((res) => {
                document.getElementById(`photo-${id}`).src = res.photo
            })
    }

    function renderCard(item, photo) {
        let postCard = document.createElement('div')
        postCard.innerHTML = `<div>...<img id="photo-${item.id}" src="${photo}"></img>...</div>`
        cards.appendChild(postCard)
        return true
    }

    function createCard(item) {
        let photo = 'https://via.placeholder.com/150x120';
        if (item.photo !== '') {
            photo = item.photo
        }
        return new Promise((resolve, reject) => {
            resolve(renderCard(item, photo))
        });
    }

    function loadRecent() {
        fetch('https://api.com/items?limit=10')
            .then((res) => { return res.json() })
            .then((res) => {
                res.data.forEach(item => {
                    createCard(item).then(() => {
                        if (item.photo == '') {
                            fetchPhoto(item.id)
                        }
                    })
                })
            })
    }

    loadRecent()

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM