Я сделал объект JavaScript, из которого я не могу перебрать или даже получить доступ к его параметрам. Что мне не хватает? - PullRequest
1 голос
/ 11 января 2020

Вот мой объект, когда я вхожу в него Chrome:

{}
de: {path: "/assets/trads/de.json", trads: {…}}
en: {path: "/assets/trads/en.json", trads: {…}}
es: {path: "/assets/trads/es.json", trads: {…}}
fr: {path: "/assets/trads/fr.json", trads: {…}}
it: {path: "/assets/trads/it.json", trads: {…}}
nl: {path: "/assets/trads/nl.json", trads: {…}}
ru: {path: "/assets/trads/ru.json", trads: {…}}
__proto__: Object

Вот его тип, когда я вхожу в него:

Object

Если я попытаюсь:

console.log(obj.en);
console.log(obj['en']);
console.log(obj.length);

Я получаю:

undefined

Если я делаю:

Object.keys(obj).forEach(e => console.log(e));
for (let i in obj) { console.log(obj[i] }
for (let i in obj) { console.log(i) }

Я ничего не получаю.

Как я сделал объект из createTradsObjFrom () (запускал на стороне клиента, получая JSON файлы, содержащие переводы для некоторого контента):

const getJson = path => {
  return new Promise((resolve, reject) => {
    $.getJSON(path, json => {
      if (!json) return reject(new Error('Error while trying to get json for assets trads.'));
      return resolve(json);
    });
  });
};

const createTradsObjFrom = (languages, tradsPaths) => {
  return new Promise((resolve, reject) => {
    try {
      const obj = {};
      languages.forEach(async (lang, index) => {
        const path = tradsPaths[index];
        obj[lang] = {
          path,
          trads: await getJson(path)
        };
      });
      console.log('obj : ', obj);
      return resolve(obj);
    }
    catch (err) {
      return reject(new Error(err));
    }
  });
};

const getTrads = currentLanguage => {
  return new Promise((resolve, reject) => {
    const tradsDir = "/assets/trads/";
    const languages = [
      "de",
      "en",
      "es",
      "fr",
      "it",
      "nl",
      "ru"
    ];
    const tradsPaths = languages.map(e => tradsDir + e + '.json');
    createTradsObjFrom(languages, tradsPaths)
    .then(trads => resolve(trads))
    .catch(err => reject(err));
  });
};

Спасибо за вашу помощь, я уже потратил слишком много времени на это. :)

1 Ответ

2 голосов
/ 11 января 2020

Сначала вы используете анти-шаблон для создания обещаний для вызовов, которые уже возвращают обещание / затем. Например, $.getJSON возвращает доступный объект, который можно использовать с await напрямую

const getJson = path => {
  return $.getJSON(path);
};

//or just change
trads: await getJson(path)
//to use $.getJSON directly
trads: await $.getJSON(path)

Во-вторых forEach() не использует обещания, поэтому его обратный вызов async не будет иметь значения, поскольку он будет не жди обещания решить. Вам нужно будет сделать createTradsObjFrom сам асинхронный c и использовать обычный l oop

const createTradsObjFrom = async (languages, tradsPaths) => {
  try {
    const obj = {};
    //set index,lang by destructuring
    for(let [index,lang] of languages.entries()){
      const path = tradsPaths[index];
      obj[lang] = {
        path,
        //just call $.getJSON directly unless needing extra work done
        trads: await $.getJSON(path)
      };
    }
    console.log('obj : ', obj);
    return obj;
  }
  catch (err) {
    //since async functions don't provide a reject method we 
    //need to throw an error to cause a rejection
    throw new Error("some error");
  }
};

Теперь вы можете просто вернуть createTradsObjFrom() или вызвать своего тогда непосредственно с него

const getTrads = currentLanguage => {
  //again don't need to make a new promise here as 
  //createTradsObjFrom will be returning one itself
  const tradsDir = "/assets/trads/";
  const languages = ["de","en","es","fr","it","nl","ru"];
  const tradsPaths = languages.map(e => tradsDir + e + '.json');
  return createTradsObjFrom(languages, tradsPaths);
};
getTrads().then(yourObj=>{
  console.log(yourObj);
  //you can now use your filled object
}).catch(err=>{
  console.log("Some error happened: ",err);
});

Относительно того, почему вы видите объект заполненным в журнале консоли, см. Этот раздел вопросов и ответов о том, как консоль оценивает объект при первом его развертывании в консоли: Is Chrome 's JavaScript консоль ленится об оценке массивов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...