javascript等待整个功能执行后再继续

时间:2020-04-14 14:14:45

标签: javascript asynchronous

我使用一种javascript使用模板(PageBuilder)构建我的html页面,使用另一种javascript翻译内容转换器。问题在于该页面在翻译之前必须完全构建,否则翻译器在加载时找不到某些项目,这就是这里发生的情况。

通过阅读日志,我可以知道问题出在PageBuilder.drawNav()中:在结束之前,Translator.load()已经启动。您能告诉我如何确保在代码可以继续之前drawNav已完全完成吗?

主要js

import PageBuilder from "/js/page-builder.js";
import Translator from "/js/translator.js";

var pageBuilder = new PageBuilder();
var translator = new Translator();

pageBuilder.load().then(() => translator.load().then(() => document.getElementById(`languageButton`).onclick = function() {translator.switchLanguage(translator)}));

翻译器

/* Courtesy of: https://codeburst.io/translating-your-website-in-pure-javascript-98b9fa4ce427 */
`use strict`

class Translator {
  constructor() {
    this._lang = this.getLanguage();
    this._elements = document.querySelectorAll(`[data-i18n]`);
  }

  getLanguage() {
    var lang = navigator.languages ? navigator.languages[0] : navigator.language;

    return lang.substr(0, 2);
  }

  load(lang = null) {
    this._elements = document.querySelectorAll(`[data-i18n]`);
    console.log("Translator.load() document.querySelectorAll...");
    console.log(this._elements);
    if (lang) {
      this._lang = lang;
    }
    else {
      var re = new RegExp(`lang=([^;]+)`);
      var value = re.exec(document.cookie);
      var cookieLang = (value != null) ? unescape(value[1]) : null;
      if (cookieLang) {
        this._lang = cookieLang;
      }
    }

    return fetch(`/json/lang-${this._lang}.json`)
      .then((res) => res.json())
      .then((translation) => {
        this.translate(translation);
      })
      .then(this.toggleLangTag())
      .then(document.cookie = `lang=${this._lang};path=/`)
      .then(() => {
        console.log("Translator.load() --end document.querySelectorAll...");
        console.log(this._elements);
      })
  }

  translate(translation) {
    console.log("translate(translation)");
    this._elements.forEach((element) => {
      var keys = element.dataset.i18n.split(`.`);
      var text = keys.reduce((obj, i) => obj[i], translation);

      if (text) {
        element.innerHTML = text;
      }
      else {
        element.innerHTML = `key ${keys} not found for ${this._lang}!`
      }
    });
  }

  toggleLangTag() {
    if (document.documentElement.lang !== this._lang) {
      document.documentElement.lang = this._lang;
    }
  }

  switchLanguage(translator) {
    var availableLang = [`en`, `fr`];
    var currentLangIndex = availableLang.indexOf(translator._lang);
    var nextLang = availableLang[(currentLangIndex + 1)%availableLang.length];
    translator.load(nextLang);
  }
}

export default Translator;

PageBuilder

`use strict`

class PageBuilder {
  constructor() {
    this._nav = document.getElementsByTagName(`nav`)[0];
    this._footer = document.getElementsByTagName(`footer`)[0];
    this._url = window.location.href;
  }

  load() {
    return this.drawFooter()
      .then(() => fetch(`/json/menu.json`))
      .then((res) => res.json())
      .then((jsonMenu) => {
        this.drawNav(jsonMenu);
      })
  }

  drawFooter() {
    console.log("drawFooter()");
    return fetch(`/templates/footer.html`)
      .then((res) => res.text())
      .then((resText) => {
        console.log(`this._footer=${this._footer}`);
        console.log(`resText=${resText}`);
        this._footer.innerHTML = resText;
        console.log("drawFooter()--end");
        console.log("PageBuilder.drawFooter() document.querySelectorAll...");
        console.log(document.querySelectorAll(`[data-i18n]`));
      })
  }

  drawNav(jsonMenu) {
    console.log("drawNav(jsonMenu)");
    var htmlMenu = ``;
    return fetch(`/templates/site-title-div.html`)
      .then((res) => res.text())
      .then((resText) => {
        htmlMenu = resText;
        console.log(`htmlMenu=${htmlMenu}`);
      })

      .then(() => {
        htmlMenu += `<ul>`;
        var previousParent = `/`;
        var ulOpen = false;

        for(var i = 0; i < jsonMenu.length; i++) {
          var jsonMenuItem = jsonMenu[i];

          var regexp = /http:\/\/cypher-f\.com((\/[a-z\-]*)?(\/[a-z\-]+)?)/g;
          var match = regexp.exec(this._url);
          var currentPageFullUrl  = match[0];
          var currentPageFullHref = match[1];
          var currentPageParent   = match[2];
          var currentPageLevel2   = match[3];

          var openingUl = ``;
          var closingUl = ``;
          var jsonParent = jsonMenuItem[`parent`];

          if ((jsonParent === `/`) || (jsonParent === currentPageParent)) {
            if (jsonParent != previousParent) {
              if (ulOpen) {
                htmlMenu += `</ul>`;
                ulOpen = false;
              }
              if (jsonParent != `/`) {
                htmlMenu += `<ul>`;
                ulOpen = true;
              }
            }


            var material_icon = jsonMenuItem[`material-icon`];
            var href = jsonMenuItem[`href`];
            var i18n = jsonMenuItem[`data-i18n`];
            var active = (currentPageFullHref === jsonMenuItem.href ? ` class="active"` : ``);
            htmlMenu += `<li${active}><i class="material-icons">${material_icon}</i><a href="${href}" data-i18n="${i18n}"></a></li>`;
            previousParent = jsonParent;
          }
        }

        if (ulOpen) {
          htmlMenu += `</ul>`;
        }
        htmlMenu += `</ul>`;
        this._nav.innerHTML = htmlMenu;
        console.log("drawNav(jsonMenu)--end");
        console.log("PageBuilder.drawNav() document.querySelectorAll...");
        console.log(document.querySelectorAll(`[data-i18n]`));
      })
  }
}

export default PageBuilder;

1 个答案:

答案 0 :(得分:1)

您需要在return呼叫之前添加this.drawNav()

  load() {
    return this.drawFooter()
      .then(() => fetch(`/json/menu.json`))
      .then((res) => res.json())
      .then((jsonMenu) => {
        return this.drawNav(jsonMenu);
      })
  }

我认为您在这里还有一个额外的括号.then(this.toggleLangTag())