2015-03-21 18 views
8

Attualmente sto provando a inviare a un array (attributo all'interno di un modello Mongo), da un elenco di elementi ricevuti tramite una richiesta. Da questi elementi, faccio un loop attraverso di essi per vedere quale è attualmente nel db e, in caso contrario, creo un nuovo oggetto e provo a salvarlo. Sto usando le promesse per portare a termine questo compito, ma non sono in grado di capire perché l'array è vuoto dopo che tutte le promesse si sono avverate.Node.js Promette: Invia all'array in modo asincrono e salva

var q  = require('q'); 

var items_to_get = ['1', '2', '3']; // example array 

var trans = new Transaction({ 
    items : [] 
}); 

var promises = []; 

for (var i = 0; i < items_to_get.length; i++) { 

    var ith = i; //save current i, kinda hacky 
    var deferred = q.defer(); //init promise 

    //find an existing item 
    Item.findOne({simcode: items_to_get[ith]}, function(err, item) { 
     trans.items.push(item); // push item to transaction 
     deferred.resolve(item); // resolve the promise 
    }); 
    promises.push(deferred); // add promise to array, can be rejected or fulfilled 
}; 

q.allSettled(promises).then(function(result) { 
    console.log(trans.items); //is empty 
    trans.save(); 
} 

EDIT Risolto: Codice soffietto, sulla base di http://jsbin.com/bufecilame/1/edit?html,js,output .. crediti andare a @macqm

var items_to_get = ['1', '2', '3']; 
var promises  = []; //I made this global 

items_to_get.forEach(item) { 
    upsertItem(item); 
} 

q.allSettled(promises).then(function(result) { 
    //loop through array of promises, add items 
    result.forEach(function(res) { 
    if (res.state === "fulfilled") { 
     trans.items.push(res.value); 
    } 
    }); 
    trans.save(); 
    promises = []; //empty array, since it's global. 
} 

//moved main code inside here 
function upsertItem(item) { 
    var deferred = q.defer(); //init promise 
    //find an existing item 
    Item.findOne({simcode: item}, function(err, item) { 
    deferred.resolve(item); // resolve the promise 
    // don't forget to handle error cases 
    // use deffered.reject(item) for those 
    }); 
    promises.push(deferred); // add promise to array 
} 

risposta

0

Invece di

promises.push(deferred); 

... provare ...

promises.push(deferred.promise); 

Inoltre, dal momento che le promesse stanno risolvendo alla voce che è stato salvato in ogni caso, è possibile utilizzare il risultato di q.allSettled(...) come i vostri articoli:

q.allSettled(promises).then(function(results) { 
    trans.items = results; 
    trans.save(); 
}); 
+1

Sembra che ogni risultato sarà un oggetto della struttura '{state: ..., value: ...}', dove 'value' è un oggetto che vuoi, quindi potresti dover fare un ulteriore passaggio per ottenere fuori. – macqm

2

Ecco come ho fatto senza librerie 3rd party.

Dato che avevo solo bisogno di posticipare e sono su ES2017 Ho pensato che fosse meglio non complicare eccessivamente le cose con dipendenze non necessarie.

'use strict'; 

/** 
* @param {function(*)} callee 
* @param {Array} args 
* @returns {Promise.<*>} 
*/ 
const defer = (callee, args) => { 
    return new Promise(resolve => { 
     resolve(callee(...args)); 
    }); 
}; 

/** 
* @param {Number} one 
* @param {Number} two 
* @param {Number} timeout 
* @returns {Promise.<Number>} 
*/ 
const asyncFunction = (one, two, timeout) => { 
    return new Promise(resolve => { 
     setTimeout(resolve, timeout, one + two); 
    }); 
}; 

let promises = []; 
promises.push(defer(asyncFunction, [3, 7, 0])); // returns immediately 
promises.push(defer(asyncFunction, [10, 20, 100])); // returns after 100ms 
promises.push(defer(asyncFunction, [55, 45, 50])); // returns after 50ms 

Promise.all(promises).then(results => { 
    console.log(results); 
}); 

esegue il codice di cui sopra e si otterrà [ 10, 30, 100 ].

+0

Grazie amico !!!!!!!!! – Vesper

Problemi correlati