首页 > 解决方案 > javascript 多函数回调语法

问题描述

我无法理解回调语法,请你帮我重写我的代码,以便它按以下顺序执行:

MenuBuilder.load()
MenuBuilder.draw()
Translator.load()

(在我的情况下,它按 MenuBuilder.load()、Translator.load()、MenuBuilder.draw() 的顺序执行,所以它不符合我的要求)

onload.js

import MenuBuilder from "./menu-builder.js";
import Translator from "./translator.js";

var menuBuilder = new MenuBuilder();
var translator = new Translator();

menuBuilder.load();
translator.load();

菜单-builder.js

"use strict"

class MenuBuilder {
  constructor() {
    this._nav = document.getElementsByTagName("nav")[0];
    this._url = window.location.href;
  }

  load() {
    console.log("MenuBuilder.load() start");
    fetch(`/json/menu.json`)
      .then((res) => res.json())
      .then((jsonMenu) => {
        this.draw(jsonMenu);
      })
      /*.catch(() => {
        console.error(`Could not load ${this._lang}.json.`);
      });*/
      console.log("MenuBuilder.load() end");
  }

  draw(jsonMenu) {
    console.log("MenuBuilder.draw(jsonMenu) start");
    var htmlMenu = `<div id="siteTitleDiv"><p id="siteTitle" data-i18n="general.title"></p><p id="siteTitleShadow" data-i18n="general.title-shadow"></p><p id="siteSubtitle"data-i18n="general.subtitle"></p></div><ul>`;
    for(var i = 0; i < jsonMenu.length; i++) {
      var menuItem = jsonMenu[i];

      var regexp = /http:\/\/cypher-f\.com\/(([a-z\-]*\/)?([a-z\-]*\/))?/g;
      var fullPage = "something format_abc";
      var match = regexp.exec(this._url);
      var level_1 = match[1];
      var level_2 = match[3];
      var parent = match[2];
      var full_suffix = match[0];

      if ((parent == null) || (menuItem.parent === parent)) {
        var material_icon = menuItem["material-icon"];
        var href = menuItem["href"];
        var i18n = menuItem["data-i18n"];
        htmlMenu += `<li><i class="material-icons">${material_icon}</i><a href="${href}" data-i18n="${i18n}"></a></li>`;
      }
    }
    htmlMenu += `</ul>`;
    this._nav.innerHTML = htmlMenu;
    console.log("MenuBuilder: nav.innerHTML");
    console.log(this._nav.innerHTML);
    console.log("MenuBuilder: document.elements");
    console.log(document.querySelectorAll("[data-i18n]"));
    console.log("MenuBuilder.draw(jsonMenu) end");
  }
}

export default MenuBuilder;

翻译器.js

"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) {
    console.log("Translator.load() start");
    console.log("this._elements");
    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;
      }
    }

    fetch(`/i18n/${this._lang}.json`)
      .then((res) => res.json())
      .then((translation) => {
        this.translate(translation);
      })
      .then(this.toggleLangTag())
      .then(document.cookie = `lang=${this._lang};path=/`)
      /*.catch(() => {
        console.error(`Could not load ${this._lang}.json.`);
      });*/
    console.log("Translator.load() end");
  }

  translate(translation) {
    console.log("Translator.load(translation) start");
    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}!`
      }
    });
    console.log("Translator.load(translation) end");
  }

  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;

很抱歉,我知道这是一个新手问题,但我已经三年没有编程了。

标签: javascript

解决方案


你在这里使用 Promises,所以你想坚持那个范式。返回从fetch调用返回的承诺,然后“链接”该承诺以调用翻译器。

  load() {
    console.log("MenuBuilder.load() start");
    // The return here gives control of the promise to the caller...
    return fetch(`/json/menu.json`)
      .then((res) => res.json())
      .then((jsonMenu) => {
        this.draw(jsonMenu);
      })
      /*.catch(() => {
        console.error(`Could not load ${this._lang}.json.`);
      });*/
      console.log("MenuBuilder.load() end");
  }

所以回到 onload.js 你可以使用返回的承诺在完成后menuBuilder.load()调用。translator.load()menuBuilder.load()

import MenuBuilder from "./menu-builder.js";
import Translator from "./translator.js";

var menuBuilder = new MenuBuilder();
var translator = new Translator();

menuBuilder.load().then(() => translator.load());

推荐阅读