0

I want to update the json object model values like the code below. But it does not seems to update the model when I change the values.

I have tried removing the async code, that seems to work. why async code does not to work? Can some one please explain me. Thanks

var json = {
  lang: "es",
  country : "Spain", 
  city : {
    cityname : "name"
  }  
};

async function asynctranslateText() {
  return new Promise((resolve, reject) => {
    resolve("OK");
  });
}

async function modifyJson(en) {
  Object.keys(en).forEach(async function (item) {
    if (typeof en[item] === 'object') {
      await modifyJson(en[item]);
    } else {
      en[item] = await asynctranslateText();
    }    
  });
}

 (async () => {
  await modifyJson(json);
  console.log(json);
 })();

Output
{ lang: 'es', country: 'Spain', city: { cityname: 'name' } }

Expected output:
{ lang: 'OK', country: 'OK', city: { cityname: 'OK' } }
fifa chapman
  • 531
  • 1
  • 4
  • 9
  • You have an await call inside `modifyJson` so this function needs to be async, your editor probably detect this error – Sébastien B Sep 26 '19 at 08:24
  • 1
    And why do you need `async-await` here? – Daniyal Lukmanov Sep 26 '19 at 08:25
  • Please learn [the difference between JSON and the Object Literal Notation](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation). – str Sep 26 '19 at 08:25
  • thanks. i have updated the code again. please take a look – fifa chapman Sep 26 '19 at 08:27
  • 1
    This function `asynctranslateText` doesn't make any sense. And there is no need to put `async` in front of it. – Daniyal Lukmanov Sep 26 '19 at 08:28
  • @DaniyalLukmanov there is a api call, for simplicity of this example i have returned "OK" – fifa chapman Sep 26 '19 at 08:31
  • 1
    Currently you need `modifyJson` to return a promise so that it can properly be awaited. You should change `forEach` to `map` and wrap that inside of [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) – Khauri Sep 26 '19 at 08:34
  • @fifachapman but if it's returning a promise then you only need to await the promise itself, not the function. The function is not asynchronous as it just returns a promise to await. – Mayron Sep 26 '19 at 08:36
  • Try to use regular `for loop`. If that will work out, then you need to change your current approach if you want to use `forEach` – Daniyal Lukmanov Sep 26 '19 at 08:38
  • An async function inside a foreach is probably not doing what you expect, try a `for of` – Sébastien B Sep 26 '19 at 08:41

2 Answers2

2

modifyJson should return a promise in order to be awaited.

Since functions marked async implicitly return promises, you can use Array.map as opposed to forEach with an async function to generate an array of promises.

Then simply use Promise.all to wait for all of them to complete.

Note that modifyJson and asyncTransalateText itself here doesn't need to be marked as async. Typically a function should not be marked as async AND return a promise.

var json = {
  lang: "es",
  country: "Spain",
  city: {
    cityname: "name"
  }
};

function asynctranslateText() {
  return new Promise((resolve, reject) => {
    resolve("OK");
  });
}

function modifyJson(en) {
  return Promise.all(Object.keys(en).map(async function(item) {
    if (typeof en[item] === 'object') {
      await modifyJson(en[item]);
    } else {
      en[item] = await asynctranslateText();
    }
  }));
}

(async() => {
  await modifyJson(json);
  console.log(json);
})();
Khauri
  • 3,753
  • 1
  • 11
  • 19
2

If you use a for .. of loop to enumerate the object keys, the result will be as expected.

The original issue is that modifyJson will not have executed when we log the output.

var json = {
  lang: "es",
  country : "Spain", 
  city : {
    cityname : "name"
  }  
};

async function asynctranslateText() {
  return new Promise((resolve, reject) => {
    resolve("OK");
  });
}

async function modifyJson(en) {
 for(let item of Object.keys(en)) {
    if (typeof en[item] === 'object') {
      await modifyJson(en[item]);
    } else {
      en[item] = await asynctranslateText();
    }
  }
}

 (async () => {
  await modifyJson(json);
  console.log(json);
 })();
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40