Iterando a través de una matriz en JS y promesas simples (web3/pudding)

Esto podría tener más que ver con mi falta de comprensión de algunos conceptos básicos de JS, sin embargo, está en el contexto de ethereum/web3, así que aquí va.

Tengo publicaciones de matriz pública en mi contrato y una variable global en JS del mismo nombre.

Usando el marco de trufa/pudín en la interfaz, intento iterar a través de la matriz haciendo algo como esto:

length = 3;
posts = new Array(length);
for(i = 0; i < length; i++ ){
  social.posts.call(i).then(function(v){
    posts[i] = v;
  });
}

Sin embargo, al depurar, descubrí que la función anónima se ejecuta solo una vez y con i igual a 3 . posts[3] se establece y nada más. Debo estar haciendo algo tonto aquí. Por favor ayuda.

Editar: ahora entiendo que el problema se debe a las promesas, pero ¿hay otra forma de recuperar fácilmente los valores de matriz del contrato? El pudín estaba destinado a ayudar con esto.

Respuestas (3)

El problema es el resultado de usar una Promesa de Javascript (proporcionada por Pudding) que envuelve la llamada. Si realizó la misma llamada sin un contenedor Promise, funcionaría como esperaba. Pero en su caso, la Promesa no se resuelve hasta que llega al final del ciclo.

¿Está diciendo que para esta llamada específica debería dejar a Pudding e ir con la llamada raw web3? Eso requeriría que inicialice la instancia del contrato desde cero nuevamente usando web3, etc. Pensé que la idea de Pudding era simplificar esas cosas. Además, me confundió porque en el documento de trufas aquí decía que las llamadas regresan inmediatamente sin esperar.

Tu puedes hacer:

var posts = [0,1,2,3].map(index => social.posts.call(index));

Promise.map(posts, post => {
  // Resolved Post Value
  console.log(post);
})
Promise.map no es estándar. Usar:Promise.all(posts).then(posts => { ... })

Nunca he oído hablar del marco de trufa/pudín. Pero supongo que este es un problema de cierre.

el valor de i en la función anónima proviene del valor de i fuera de la función anónima. Hay un objeto Closure para cada función anónima que contiene las variables que usa la función anónima donde esas variables no son globales ni locales. Así que supongo que este fragmento de código está dentro de alguna otra función. Llamemos a esa otra función A. Cuando el valor de la variable i cambia dentro de la función A, entonces cambian los valores de TODAS las variables i en los cierres. Debido a que la función anónima se ejecuta después de que la función A termina de ejecutarse, usan el valor de i = 3. Una solución es poner un IFFE alrededor de la función anónima y pasar el valor de i al IFFE. Entonces, el valor de la variable i para cada función anónima no cambiaría después de la primera vez que se me asignó un valor en la función anónima.

Oye, funciona, aunque me da una advertencia sobre no pasar exactamente una función anónima. Además, pensé que entendía la idea de las promesas, pero en este caso no estoy seguro. La llamada es síncrona y también debe regresar de inmediato de acuerdo con el documento . Otra cosa es que dices que todas las variables i cambian, pero según mi depuración, la función anónima se ejecutaría anteriormente solo una vez y no tres veces. Había puesto un registro de consola allí para registrar el valor de i y solo veía un '3'
En realidad no. No lo hice exactamente bien. Lo tenía {(function(v){ posts[i] = v; })(i)}al principio, pero es incorrecto ya que el valor de v no se inyecta en la función ahora y i se pasa como v. Por lo tanto, ¿hay alguna forma de hacer esto con tal cierre?