如何延迟异步功能Javascript?

时间:2020-05-11 16:47:06

标签: javascript

我的课程当然是一个单页面的应用程序。我在脚本中有两个功能。其中一个负责页面的结构(部分html),另一个负责页面内容的过滤。 m在控制台中出现错误“无法读取null的'firstChild'属性”。我假设由于第一个函数是异步的,因此第二个在第一个函数之前完成,并且我得到了一个错误。但这不能正常工作。如何解决?

//navigation for the single page app.
// It loads html code from external html files.
// External HTML pages after visited once are then stored.
// Keys correspond to piece identifiers.
// Values are the text content of each loaded external HTML file.
var partialHtmlCache = {};

// HTTP GET request using XMLHttpRequest.
// Fetches the file at the given path, then
// calls the callback with the text content of the file.
function fetchFile(path, callback) {
  // Create a new AJAX request for fetching the partial HTML file.
  var request = new XMLHttpRequest();

  request.onload = function () {
    callback(request.responseText);
  };
  request.open("GET", path);
  request.send(null);
}

// This function implements a simple cache.
function getContent(pieceId, callback) {
  // If the page has been fetched before,
  if (partialHtmlCache[pieceId]) {
    // Pass the previously fetched content to the callback.
    callback(partialHtmlCache[pieceId]);
  } else {
    // If the page has not been fetched before.
    fetchFile(pieceId + ".html", function (content) {
      // Store the fetched content in the cache.
      partialHtmlCache[pieceId] = content;

      // Pass the newly fetched content to the callback.
      callback(content);
    });
  }
}

// Updates the content based on the piece identifier.
function navigate() {
  // Get a reference to the "contentcont" div.
  var contentDiv = document.getElementById("contentcont"),
    // Remove "#" character.
    pieceId = location.hash.substr(1);

  // Change the "contentcont" div innerHTML based on the piece identifier.
  getContent(pieceId, function (content) {
    contentDiv.innerHTML = content;
  });
}

// If no fragment identifier is provided,
if (!location.hash) {
  // default to #home.
  location.hash = "#home";
}

// Navigate once to the initial fragment identifier.
navigate();

// Navigate whenever the fragment identifier value changes.
window.addEventListener("hashchange", navigate);
//Card filter on Tutorials Page

//Array with Cards
const cards = [
  //Fundamentals
  {
    title: "Auzre basics",
    description: "Azure Fundamentals",
    category: "Fundamentals",
    src: "https://www.youtube.com/embed/KXkBZCe699A",
  },
 
];
function showCards() {
  // Div containing cards with video Tutorials.
  var cards_container = document.getElementById("cards");
  // Remove all current card divs so we can replace with new ones below.
  // If we don't do this the divs we add below will just be added after whatever
  // is already on the page.
  while (cards_container.firstChild) {
    cards_container.removeChild(cards_container.firstChild);
  }

  var selected_category = document.getElementById("category-selector").value;

  for (i = 0; i < cards.length; i++) {
    var current_card = cards[i];

    // The following two variables are boolean values
    // category_correct is equal to true either if the selected option is all
    // or the current Cards category value is the same as that selected.
    var category_correct =
      selected_category == "all" || current_card.category == selected_category;

    // Only show Cards with the correct category
    if (category_correct) {
      var bootcolumn = generate_card_html(current_card);
      cards_container.appendChild(bootcolumn);
    }
  }
}

function generate_card_html(card) {
  var bootcolumn = document.createElement("div");
  bootcolumn.setAttribute("class", "col-12 col-md-6 col-xl-3"); //
  var card_div = document.createElement("div");
  card_div.setAttribute("class", "card"); // Give div class="card"
  var embed_div = document.createElement("div");
  embed_div.setAttribute("class", "embed-responsive embed-responsive-16by9"); // add responsive embed.
  var iframe = document.createElement("iframe"); // add iframe parameters
  iframe.width = "320";
  iframe.height = "220";
  iframe.src = card.src;
  iframe.frameborder = "0";
  iframe.allow =
    "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture";
  iframe.allowfullscreen;
  var card_body = document.createElement("div");
  card_body.setAttribute("class", "card-body");
  var header = document.createElement("h5");
  header.setAttribute("class", "card-title");
  header.innerHTML = card.title;
  var description = document.createElement("p");
  description.setAttribute("class", "card-text");
  description.innerHTML = card.description;

  bootcolumn.appendChild(card_div);
  card_div.appendChild(embed_div);
  embed_div.appendChild(iframe);
  card_div.appendChild(card_body);
  card_body.appendChild(header);
  card_body.appendChild(description);

  return bootcolumn;
}
showCards();
//Partial Html thats being injected into #contentcont


<label for="category-selector">Category: </label>
<select name="category" id="category-selector" onchange="showCards()">
  <option value="all">All</option>
  <option value="Fundamentals">Fundamentals</option>
  <option value="Infrastructure">Infrastructure</option>
  <option value="ai">AI & Data</option>
  <option value="iot">Internet of things</option>
  <option value="Security">Security</option>
  <option value="devops">DevOps</option>
  <option value="WebMobile">Web & Mobile</option>
</select>
<div class="row cards" id="cards"></div>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
      integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
      crossorigin="anonymous"
    />
    <link rel="stylesheet" href="assets/style.css" />
    <link
      rel="stylesheet"
      href="https://use.fontawesome.com/releases/v5.11.2/css/all.css"
    />
    <link
      rel="stylesheet"
      href="https://use.fontawesome.com/releases/v5.11.2/css/v4-shims.css"
    />

  </head>
  <body>
   

    <div class="container-fluid">
      <div class="main">
        <nav class="navbar navbar-expand-lg fixed-top">
          <a class="navbar-brand" href=""></a>

          <button
            class="navbar-toggler custom-toggler"
            type="button"
            data-toggle="collapse"
            data-target="#navbar-content"
            aria-controls="navbar-content"
            aria-expanded="false"
            aria-label="Toggle navigation"
          >
            <span class="navbar-toggler-icon"></span>
          </button>

          <div class="collapse navbar-collapse" id="navbar-content">
            <ul class="navbar-nav ml-auto mt-2 mt-lg-0">
              <li class="nav-item active">
                <a class="nav-link" href="#home"
                  >Home<span class="sr-only">(current)</span></a
                >
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#categories"
                  >Categories</a
                >
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#tutorials">Tutorials</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#news">News</a>
              </li>
              <li class="nav-item">
                <a
                  class="nav-link"
                  href="https://www.facebook.com/"
                  target="_blank"
                  rel="noopener"
                  ><i class="fa fa-facebook-f"></i
                  ><span class="sr-only">facebook</span></a
                >
              </li>
            </ul>
          </div>
        </nav>

      
<div id="contentcont"></div>


  
        
      </div>
    </div>

    <script
      src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
      integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
      integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
      integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
      crossorigin="anonymous"
    ></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.11"></script>
    <script src="/assets/script.js"></script>

  </body>
</html>

1 个答案:

答案 0 :(得分:0)

我可以从提供的代码中学到什么:

您的JavaScript代码正在调用navigate(),随后几乎是showCards()

问题在于showCards()依赖于navigate()异步加载的内容。

与其直接调用showCards(),不如尝试修改navigate()

function navigate() {

  var contentDiv = document.getElementById("contentcont"),
    pieceId = location.hash.substr(1);

  getContent(pieceId, function (content) {
    contentDiv.innerHTML = content;

    // EDIT: now that content has been added to DOM, you can safely show cards:
    showCards();
  });
}
相关问题