Return of a promise then () for each element of an array

0

When loading the page filled an array with a $ .each and one of the values is an id of a parameter and I need to draw based on that id the description to show in a table, I have the function that returns the description but I can not load it to a variable so that it is saved in the array, how do I recover the result value for each element? Thanks

$.each(jsonTransfers, function (index, value) {
  var description = "";
  WorkFlow.Utils.GetTextParameterSelected(188, value.currencyType).then(function (result) {
   description = result;
  });
 ListTransfer.push({CurrencyDescription: description});
}
    
asked by daniela 14.08.2018 в 21:19
source

2 answers

2

I'm going to mock your WorkFlow.Utils.GetTextParameterSelected(id, currency) method basically by returning a promise that resolves after 1 second with the id, description and currency:

var descripciones = [
  'hola',
  'soy',
  'la descripción'
];

function getDescripcion(id, currency) {
  return new Promise((resolve, reject) => {
    window.setTimeout(() => {
      resolve({
        id: id,
        descripcion: descripciones[id],
        moneda: currency
      });
    }, 1000);
  });
}

In your loop $.each you are inserting promises to an array called, very imaginatively promesas . Finished the loop, you call

Promise.all(promesas).then((values) => {
   console.log(values);
});

To obtain the collection of values obtained once all the promises have been resolved. The order in which they appear is the same in which they were inserted, regardless of the order in which they were resolved.

var descripciones = [
  'hola',
  'soy',
  'la descripción'
];

var jsonTransfers = [{
    currencyType: 'USD'
  },
  {
    currencyType: 'EUR'
  },
  {
    currencyType: 'CLP'
  }
];

function getDescripcion(id, currency) {
  return new Promise((resolve, reject) => {
    window.setTimeout(() => {
      resolve({
        id: id,
        descripcion: descripciones[id],
        moneda: currency
      });
    }, 1000);
  });
}

var promesas = [];
$.each(jsonTransfers, function(index, value) {
  promesas.push(getDescripcion(index, value.currencyType));
});

Promise.all(promesas).then((respuestas) => {
  console.log(respuestas);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
answered by 15.08.2018 в 00:11
0

Playing a little with the response of amenadiel I add a callback to each promise so I do not have to wait for that returns all the items.

var descripciones = [
  'hola',
  'soy',
  'la descripción',
  'o alguna',
  'otra palabra',
  'cuanto mas items',
  'mejor se aprecia',
  'la naturaleza',
  'asíncrona del ajax'
];

var jsonTransfers = [{
    currencyType: 'USD'
  },
  {
    currencyType: 'EUR'
  },
  {
    currencyType: 'CLP'
  },
  {
    currencyType: 'GBP'
  },
  {
    currencyType: 'JPY'
  },
  {
    currencyType: 'AUD'
  },
  {
    currencyType: 'CAD'
  },
  {
    currencyType: 'SGD'
  },
  {
    currencyType: 'CNY'
  }
];

// timeout random por usar el wifi del hotel
function getDescripcion(id, currency) {
  return new Promise((resolve, reject) => {
    window.setTimeout(() => {
      resolve({
        id: id,
        descripcion: descripciones[id],
        moneda: currency
      });
    }, (Math.random() * 4 + 2) * 1000);
  });
}

// Relleno la tabla
var table = document.getElementById('transfers');
var tableBody = document.createElement('tbody');

jsonTransfers.forEach(function(itemData, index) {
  var row = document.createElement('tr');
  row.id = "item" + index;
  var cellType = document.createElement('td');
  cellType.className = "ctype";
  cellType.appendChild(document.createTextNode(itemData.currencyType));
  row.appendChild(cellType);

  var cellDesc = document.createElement('td');
  cellDesc.className = "cdesc";
  cellDesc.appendChild(document.createTextNode('?'));
  row.appendChild(cellDesc);

  tableBody.appendChild(row);
});

table.appendChild(tableBody);

// esto es masomenos un callback
var setDescription = function(itemData) {
  var cellDesc = document.getElementById('item' + itemData.id).cells[1];
  cellDesc.style.background = '';
  cellDesc.innerHTML = itemData.descripcion;
}

// para que el log no tape las cosas
var consolog = function(...cosas) {
  var logs = document.getElementById('logs');
  cosas.forEach((t) => {
    logs.innerHTML += t + " ";
  });
  logs.innerHTML += "\n";
  logs.scrollTop = logs.scrollHeight;

};

var promesas = [];
$("#dale").on("click", () => {

  // inhabilitamos el boton de pedir
  document.getElementById("dale").disabled = true;
  // limpiamos las descripciones
  consolog("-- borrar descripciones");
  jsonTransfers.forEach(function(itemData, index) {
    var cellDesc = document.getElementById('item' + index).cells[1];
    cellDesc.style.background = 'PapayaWhip';
    cellDesc.innerHTML = '--wait...';
  });

  var start = Date.now();
  consolog("0000", "-- pedir descripciones");
  $.each(jsonTransfers, function(index, value) {
    // cada promesa resuelve llamando al callback
    promesas.push(
      getDescripcion(index, value.currencyType).then((x) => {
        setDescription(x);
        consolog((Date.now() - start), JSON.stringify(x));
      })
    );
  });
  // cuando todas resuelven
  Promise.all(promesas).then(() => {
    // habilitamos el boton de pedir
    document.getElementById("dale").disabled = false;
    consolog(Date.now() - start, 'all done');
  });
});
td,
th {
  vertical-align: top;
  padding: 2px 5px 0 0;
}

.cdesc {
  min-width: 120px;
}

#logs {
  height: 240px;
  overflow-y: scroll;
  min-width: 50vw;
  background: #fafafa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <td>
        <table id="transfers">
          <thead>
            <tr>
              <th>Currency</th>
              <th>Description</th>
            </tr>
          </thead>
        </table>
      </td>
      <td><button id="dale">Traer Descriptions</button>
        <PRE id="logs"></PRE>
      </td>
    </tr>
  </tbody>
</table>
    
answered by 15.08.2018 в 02:33