首页 > 解决方案 > 显示请稍候或加载程序使用 javascript-REST API 调用

问题描述

我正在编写一个 chrome 扩展来将数据从扩展发送到公开的 REST 服务。当我收到来自 API 的响应时,我正在显示一条状态消息。我想在执行 API 调用时显示请稍候或加载程序,主要是告诉用户尚未从服务器收到响应或服务器本身已关闭。由于它是一个异步调用,我不确定将代码放在哪里来显示加载器。我需要使用回调函数吗?这是我的代码-

HTML:

<!DOCTYPE html>
<html>
<head>

</head>
<body>

<h2>Send data to system Application</h2>

<form action="/action_page.php">
  <p>Please select:</p>
  <input type="radio" id="Credentials" name="CB" value="Credentials">
  <label for="Credentials">Credentials</label><br>
  <input type="radio" id="GeneralInformation" name="CB" value="GeneralInformation">
  <label for="GeneralInformation">General Information</label><br>
  <br>  
  
   <div id="ifCredentials" style="display:none">
        <form>
            Username <input type="text" id="Username" style="line-height:3em"> <br><br>
            Password <input type="text" id="Password" style="line-height:3em"> <br><br>
            URL <input type="text" id="URL" style="line-height:3em"> <br><br>
            Environment <input type="text" id="Environment" style="line-height:3em"> <br><br>
            Labels <input type="text" id="SVLabel" style="line-height:3em"> <br><br>
        </form>
    </div>
    
     <div id="ifGeneralInformation" style="display:none">
        <form>
            Description <input type="text" id="Description" style="line-height:3em"> <br><br>
            URL <input type="text" id="GIURL" style="line-height:3em"> <br><br>
            Labels <input type="text" id="GILabel" style="line-height:3em"> <br><br>
        </form>
    </div>
        
  <br>
  <input type="submit" id="submitButton" value="Submit">
  <div id="loader" style="display:none">Please wait...   </div>
  <div id="RESTStatus" style="display:none">
    <br> Status: <label id="RESTINFO">f</label>
  </div>
</form>


<script src="script.js"></script>
</body>

</html>

JAVASCRIPT:

    document.getElementById("Credentials").addEventListener("click", showRightData);

    document.getElementById("GeneralInformation").addEventListener("click", showRightData);

    document.getElementById("submitButton").addEventListener("click", callAPI);


function showRightData() {
     console.log("hel");
  if (document.getElementById('Credentials').checked) {
        document.getElementById('ifCredentials').style.display = 'block';
        document.getElementById('ifGeneralInformation').style.display = 'none';
    }
    else if (document.getElementById('GeneralInformation').checked)
    {
        document.getElementById('ifGeneralInformation').style.display = 'block';
         document.getElementById('ifCredentials').style.display = 'none';
         chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => {
            let url = tabs[0].url;
                // use `url` here inside the callback because it's asynchronous!
                document.getElementById('GIURL').value=url;
            });
                
        
    }
        else
            {
            document.getElementById('ifGeneralInformation').style.display = 'none';
            document.getElementById('ifCredentials').style.display = 'none';
            }
}

/*window.onload = function()
{
    
    document.getElementById('GIURL').value=window.location.toString();
}*/

function callAPI() {
    
    const req = new XMLHttpRequest();
    const baseUrl = "http://localhost:8080/api/v1/cases";

    req.open("POST", baseUrl, true);
    req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");



    if (document.getElementById('Credentials').checked) {
        
        req.send(JSON.stringify(
            {
              "caseTypeID": "CB-systems-Work-Artifact",
              "processID": "pyStartCase",
              "parentCaseID": "",
              "content": {
              "ArtifactData": {
                       "ArtifactType":"Password",
                       "ArtifactUsername":document.getElementById('Username').value,
                       "ArtifactPassword":document.getElementById('Password').value,
                       "ArtifactURL":document.getElementById('URL').value,
                       "ArtifactEnvironment":document.getElementById('Environment').value,
                       "ArtifactLabels":document.getElementById('SVLabel').value
            }

        }
        }

            ));
    }
    
    else if (document.getElementById('GeneralInformation').checked)
    {
        
        req.send(JSON.stringify(
            {
              "caseTypeID": "CB-systems-Work-Artifact",
              "processID": "pyStartCase",
              "parentCaseID": "",
              "content": {
              "ArtifactData": {
                       "ArtifactType":"General",
                       "Description":document.getElementById('Description').value,
                       "ArtifactURL":document.getElementById('GIURL').value,
                       "ArtifactLabels":document.getElementById('GILabel').value
            }

        }
        }

            ));
        
        
        
    }
        
    
    
    req.onreadystatechange = function() { // Call a function when the state changes.
        if (this.readyState === XMLHttpRequest.DONE && this.status == 201) {
                      document.getElementById('RESTINFO').innerHTML = "Successfully sent data to the system! API status: "+this.status;
            document.getElementById('RESTStatus').style.display = 'block';
           
        }
        
        else
            {
            document.getElementById('RESTINFO').innerHTML = "Failed to update the system! API Status: "+this.status;
            document.getElementById('RESTStatus').style.display = 'block';
          }
        
        
    }
    
    req.onerror = function() {
        document.getElementById('RESTINFO').innerHTML = "There has been an error. The status code is "+req.status;
            document.getElementById('RESTStatus').style.display = 'block';
    }
}

标签: javascripthtmlajaxgoogle-chrome-extension

解决方案


看来您已经设置了大部分必要的代码。您需要做的就是添加行以在适当的位置显示/隐藏加载程序。

要首先显示它,请添加以下内容:

document.getElementById('loader').style.display = 'block';

就在你的两个req.send电话之前。(您可以在函数开始时只添加一次,但似乎您只在两种情况之一中发送请求,所以这必须在if语句中 - 如果两者都存在,您可能希望向用户显示一些消息其中没有向他们解释什么是错误的以及如何实际提出请求。)

然后用这个隐藏它:

document.getElementById('loader').style.display = 'none';

收到回复时。在这种情况下,我认为您的代码不正确,因为您假设一个readystatechange事件必然意味着请求已完成(成功与否),而实际上它发生在到达最终状态的各个阶段 - 请参阅此处的文档。

在回调函数中你应该做的onreadystatechange是这样的:

req.onreadystatechange = function() {
    if (this.readyState === XMLHttpRequest.DONE) {
        // request is finished, so hide loader:
        document.getElementById('loader').style.display = 'none';
        if (req.status === 201) {
            // code for successful response
        }
        else {
            // code to handle unsuccessful response
        }
    }
}

请注意,我使用req.status而不是, 以避免内部回调this.status的众所周知的问题。this

上面的粗略大纲应该按照您的意愿进行 - 但您的大部分代码都可以简化和改进。我强烈建议使用现代且广泛支持的基于 Promise 的fetch API,而不是相当老式的XMLHttpRequest.


推荐阅读