0

I don't have to wait (await) after each iteration of forEach. I don't have the right procedure. At the moment, the code is executed in the following sequence:

Load: en
Load: ru
Complete load (en)
Complete load (ru)

I need it to be like this:

Load: en
Complete load (en)
Load: ru
Complete load (ru)

This code should be used with jquery (loading data from the server), but I have reworked the code so that the data was taken directly from the code

/*
 Offline mode start
*/
var files = {
    "/public/js/json/languages.json": {
        "en": {
            "needInclude": true,
            "link": "/js/json/languages/english.json"
        },
        "ru": {
            "needInclude": false,
            "link": "/js/json/languages/russian.json"
        }
    },
    "/js/json/languages/english.json": {
        "general": {
            "authorization": "Authorization",
            "username": "Username",
            "password": "Password",
            "signin": "Sign In",
            "signup": "Sign Up",
            "restorepassword": "Restore password"
        }
    },
    "/js/json/languages/russian.json": {
        "general": {
            "authorization": "Авторизация",
            "username": "Логин",
            "password": "Пароль",
            "signin": "Войти",
            "signup": "Зарегистрироваться",
            "restorepassword": "Восстановить пароль"
        }
    }
}

function loadFile(url, doneFunction = function() {}) {
    doneFunction(files[url]);
}
/*
 Offline mode end
*/

/*
 Main code start
*/
function loadLanguage(url, overwrite = false) {
    return new Promise(resolve => {
        //$.get(url).done(function(language){
        loadFile(url, function(language) {
            try {
                Object.keys(language).forEach(function(key1) {
                    if (!isset(lang[key1])) {
                        lang[key1] = language[key1];
                    } else {
                        Object.keys(language[key1]).forEach(function(key2) {
                            if (!isset(lang[key1][key2]) || overwrite) {
                                lang[key1][key2] = language[key1][key2];
                            }
                        });
                    }
                });
                resolve(true);
            } catch (err) {
                resolve(false);
            }
        });
    });
}

function selLanguage(language) {
    //$.get("/public/js/json/languages.json").done(async function(languages){
    loadFile("/public/js/json/languages.json", function(languages) {
        Object.keys(languages).forEach(lang => {
            return new Promise(async resolve => {
                if (lang == language || languages[lang]["needInclude"] == true) {
                    console.log("Load: " + lang);
                    await loadLanguage(languages[lang]["link"], lang == language);
                    console.log("Complete load (" + lang + ")");
                    resolve();
                }
            });
        });
    });
}
/*
 Main code end
*/
selLanguage("ru");
Ponywka
  • 5
  • 1
  • Possible duplicate of [Using async/await with a forEach loop](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) – gengns Mar 10 '19 at 17:36

1 Answers1

0

Made a minor tweak to your code. Instead of doing a .foreach(), I used .map() to create functions that return a your original promise eg. () => new Promise(resolve => resolve()). This way they are not executed until the previous one is finished. Then, using a recursive function sequence(), I synchronously go through each promise.

/*
 Offline mode start
*/
var files = {
  "/public/js/json/languages.json": {
    "en": {
      "needInclude": true,
      "link": "/js/json/languages/english.json"
    },
    "ru": {
      "needInclude": false,
      "link": "/js/json/languages/russian.json"
    }
  },
  "/js/json/languages/english.json": {
    "general": {
      "authorization": "Authorization",
      "username": "Username",
      "password": "Password",
      "signin": "Sign In",
      "signup": "Sign Up",
      "restorepassword": "Restore password"
    }
  },
  "/js/json/languages/russian.json": {
    "general": {
      "authorization": "Авторизация",
      "username": "Логин",
      "password": "Пароль",
      "signin": "Войти",
      "signup": "Зарегистрироваться",
      "restorepassword": "Восстановить пароль"
    }
  }
}

function loadFile(url, doneFunction = function() {}) {
  doneFunction(files[url]);
}
/*
 Offline mode end
*/

/*
 Main code start
*/
function loadLanguage(url, overwrite = false) {
  return new Promise(resolve => {
    //$.get(url).done(function(language){
    loadFile(url, function(language) {
      try {
        Object.keys(language).forEach(function(key1) {
          if (!isset(lang[key1])) {
            lang[key1] = language[key1];
          } else {
            Object.keys(language[key1]).forEach(function(key2) {
              if (!isset(lang[key1][key2]) || overwrite) {
                lang[key1][key2] = language[key1][key2];
              }
            });
          }
        });
        resolve(true);
      } catch (err) {
        resolve(false);
      }
    });
  });
}

function selLanguage(language) {
  //$.get("/public/js/json/languages.json").done(async function(languages){
  loadFile("/public/js/json/languages.json", function(languages) {
    const promises = Object.keys(languages).map(lang => {
      return () => new Promise(async resolve => {
        if (lang == language || languages[lang]["needInclude"] == true) {
          console.log("Load: " + lang);
          await loadLanguage(languages[lang]["link"], lang == language);
          console.log("Complete load (" + lang + ")");
          resolve();
        }
      });
    });
     sequence(promises)
  });
  

}

async function sequence(promises) {
  if (!promises.length) {
    return;
  }
  await promises.shift()()
  return sequence(promises)
}
/*
 Main code end
*/
selLanguage("ru");
Jordan Maduro
  • 938
  • 7
  • 11