2021年2月5日星期五

forEach loop behaving strangely with called function values logged at end of the loop instead of during

I am trying to apply a node javascript translation function (ive put it at the end of the post because it is quite long) to loop over an array of values. However when i loop for some reason i'm only getting certain parts of my looped function to appear after the loop has completed: Allow me to make this more clear:

array = [["hello", "hello" ],           ["my", "my",  ],           ["name", "name" ],           ["is", "my" ],           ["joe", "joe"]]    function process (item,index){       const translate = require('@vitalets/google-translate-api');                console.log('loopaction'); //this shows that the loop is executing      translate(item[0], {to: 'sp'}).then(result => {      console.log(result.text);      }).catch(err => {      console.error(err);  })      array.forEach(process);   // Applying the function process to the array in a ForEach loop  

from this i am getting

loopaction loopaction loopaction loopaction loopaction

hola mi nombre es joe

So it seems that the forEach loop is completing before the values are being allowed to be displayed. Which is something i really don't understand since the array values are being translated correctly and then logged out in the correct order. As if they had been stored in the memory for later. And then called at the end of the forEach loop order.

The translate function looks like this:

function translate(text, opts, gotopts) {  opts = opts || {};  gotopts = gotopts || {};  var e;  [opts.from, opts.to].forEach(function (lang) {      if (lang && !languages.isSupported(lang)) {          e = new Error();          e.code = 400;          e.message = 'The language \'' + lang + '\' is not supported';      }  });  if (e) {      return new Promise(function (resolve, reject) {          reject(e);      });  }    opts.from = opts.from || 'auto';  opts.to = opts.to || 'en';  opts.tld = opts.tld || 'com';    opts.from = languages.getCode(opts.from);  opts.to = languages.getCode(opts.to);    var url = 'https://translate.google.' + opts.tld;  return got(url, gotopts).then(function (res) {      var data = {          'rpcids': 'MkEWBc',          'f.sid': extract('FdrFJe', res),          'bl': extract('cfb2h', res),          'hl': 'en-US',          'soc-app': 1,          'soc-platform': 1,          'soc-device': 1,          '_reqid': Math.floor(1000 + (Math.random() * 9000)),          'rt': 'c'      };        return data;  }).then(function (data) {      url = url + '/_/TranslateWebserverUi/data/batchexecute?' + querystring.stringify(data);      gotopts.body = 'f.req=' + encodeURIComponent(JSON.stringify([[['MkEWBc', JSON.stringify([[text, opts.from, opts.to, true], [null]]), null, 'generic']]])) + '&';      gotopts.headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';        return got.post(url, gotopts).then(function (res) {          var json = res.body.slice(6);          var length = '';            var result = {              text: '',              pronunciation: '',              from: {                  language: {                      didYouMean: false,                      iso: ''                  },                  text: {                      autoCorrected: false,                      value: '',                      didYouMean: false                  }              },              raw: ''          };            try {              length = /^\d+/.exec(json)[0];              json = JSON.parse(json.slice(length.length, parseInt(length, 10) + length.length));              json = JSON.parse(json[0][2]);              result.raw = json;          } catch (e) {              return result;          }            if (json[1][0][0][5] === undefined) {              // translation not found, could be a hyperlink?              result.text = json[1][0][0][0];          } else {              json[1][0][0][5].forEach(function (obj) {                  if (obj[0]) {                      result.text += obj[0];                  }              });          }          result.pronunciation = json[1][0][0][1];            // From language          if (json[0] && json[0][1] && json[0][1][1]) {              result.from.language.didYouMean = true;              result.from.language.iso = json[0][1][1][0];          } else if (json[1][3] === 'auto') {              result.from.language.iso = json[2];          } else {              result.from.language.iso = json[1][3];          }            // Did you mean & autocorrect          if (json[0] && json[0][1] && json[0][1][0]) {              var str = json[0][1][0][0][1];                str = str.replace(/<b>(<i>)?/g, '[');              str = str.replace(/(<\/i>)?<\/b>/g, ']');                result.from.text.value = str;                if (json[0][1][0][2] === 1) {                  result.from.text.autoCorrected = true;              } else {                  result.from.text.didYouMean = true;              }          }            return result;      }).catch(function (err) {          err.message += `\nUrl: ${url}`;          if (err.statusCode !== undefined && err.statusCode !== 200) {              err.code = 'BAD_REQUEST';          } else {              err.code = 'BAD_NETWORK';          }          throw err;      });  });  }  

I realise there is a promise format and the problem im having may have to do with the asychronisity of the function and how the long the promise is taking to get resolved. I cant seem to figure out why the promise is not resolving or displaying after my forEach function is completely looped yet it seems to be saved correctly and in the correct order. Very odd.

Any ideas about what is it about the function translate() that is making this happen? Is there anyway i can rewrite my function process () to make sure that the translate functions resolved promise and the .then() in function process () is fully executed before moving on?

https://stackoverflow.com/questions/66072800/foreach-loop-behaving-strangely-with-called-function-values-logged-at-end-of-the February 06, 2021 at 09:43AM

没有评论:

发表评论