【问题标题】:Add a loading animation while the promise loads and displays the JSON在 Promise 加载并显示 JSON 时添加加载动画
【发布时间】:2017-06-15 12:09:48
【问题描述】:

我完成了这个简单应用程序的功能方面,但现在我还想添加一些好的用户体验,所以我想在 JSON 加载时以及在它显示承诺结果之前添加一个加载动画(微调器),但我似乎无法通过谷歌搜索找到解决方案。

这是笔:https://codepen.io/kresimircoko/pen/ZLJjVM

这里是 JavaScript 代码:

const API_KEY = '?api_key=625023d7336dd01a98098c0b68daab7e';
const root = 'https://www.warcraftlogs.com:443/v1/';
const zonesBtn = document.querySelector('#zones');
const responseList = document.querySelector('#response');
console.clear();

const requestJSON = objType => {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.onload = function() {
            try {
                resolve(JSON.parse(this.responseText));
            }
            catch (e) {
                reject(e);
            }
        };
        xhr.onerror = reject;
        xhr.open('GET', root + objType + API_KEY);
        xhr.send();
    });
};

function displayBosses(zoneID) {
    let bosses = document.querySelectorAll(`.bosses[data-zoneid="${zoneID}"]`);
    requestJSON('zones')
        .then(data => {
            let output = '';
            data.find(zone => 
                zone.id === parseInt(zoneID, 10)
            ).encounters.map(encounter => {
                output += `<li class="boss" data-zoneid="${zoneID}">${encounter.name}</li>`;
                bosses.forEach(boss => {
                    boss.innerHTML = output;
                });
            }).join('');
    });
}

function displayZones() {
    let output = '';
    requestJSON('zones')
        .then(zones => {
            return zones.map(zone => {
                output += `
                    <ul data-zoneid="${zone.id}" class="zones"> 
                        <span>${zone.name}</span>
                        <ul data-zoneid="${zone.id}" class="bosses"></ul>
                    </ul>`;
                response.innerHTML = output;
            }).join('');
        })
        .then(responseList.style.display = 'flex');
}

zonesBtn.addEventListener('click', displayZones);
responseList.addEventListener('click', evt => {
    const target = evt.target.parentElement;
    const zoneID = target.dataset.zoneid;
    displayBosses(zoneID);
    if (target.classList.contains('clicked'))
        target.classList.remove('clicked');
    else 
        target.classList.add('clicked')
});

【问题讨论】:

  • 您是要自己创建微调器还是将您引导到一个好的微调器插件/库/sn-p?简而言之,您需要在发送数据的 xhr 调用之前或之后调用渲染微调器的函数,然后在数据返回时移除微调器。最坏的情况,只需在 html 顶部放置一个半透明的灰色叠加层,因此 UI(绝对位置等)有点“不可用”,并使用 css 规则 cursor: wait; 将光标指针更改为默认微调器
  • @Shilly 我会自己创建微调器,我想避免使用库和外部代码,至少在这种情况下是这样。所以你的意思是我应该在displayZones函数的第一个.then中调用spinner rendering function?随时纠正我:)
  • 不,在第一个'then'之前,因为'then'只有在数据返回时才会解析。因此,要么向你的 ajax 调用添加一个回调参数,要么让 ajax 调用始终显示一个微调器,或者在启动异步 requestJSON.then() 之前调用它。你需要在第一个“then”中再次删除微调器。有点像:function displayBosses(zoneID) { showSpinner(); requestJSON().then( hideSpinner(); data.find(.......
  • @Shilly 听起来应该可以解决问题

标签: javascript json ecmascript-6 es6-promise


【解决方案1】:

微调器是一个封装在spinner div 中的FontAwesome 图标,我们控制其display 属性以在单击按钮时显示,但在promise 已解决时隐藏。

function displayZones() {
    if (!this.classList.contains('open')) {
        spinner.style.display = 'block';
        this.classList.add('open');
    }
    let output = '';
    requestJSON('zones')
        .then(zones => {
            spinner.style.display = 'none';
            return zones.map(zone => {
                output += `
                    <ul data-zoneid="${zone.id}" class="zones"> 
                        <span>${zone.name}</span>
                        <ul data-zoneid="${zone.id}" class="bosses"></ul>
                    </ul>`;
                response.innerHTML = output;
            }).join('');
        })
        .then(responseList.style.display = 'flex');
}

【讨论】:

    猜你喜欢
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    相关资源
    最近更新 更多