2016-11-28 7 views
1

Ich bin neu zu versprechen, ich versuche RSVP Versprechen in Node.js mit PostgreSQL zu verwenden und ich mache es falsch, höchstwahrscheinlich. Vorschläge, wie Sie das beheben oder den Code verbessern können, sind willkommen.Resolve Array von Versprechen node.js

Ich versuche zu erreichen: nach dem Empfangen von Daten - verarbeiten Sie die Daten, um SQL-Update-Abfragen zu erstellen und wenn sie fertig sind - führen Sie sie aus. Daten hier sind Array von Benutzer-IDs.

Was nicht funktioniert: Ich Array von Array von Versprechen erhalten, die nicht beheben, habe ich versucht, das Array zu lösen wie so:

var promise4all = RSVP.all(
    updateQueries.map((innerPromiseArray) => { 
    return RSVP.all(innerPromiseArray); 
    }) 
); 

promise4all.then((promiseGroupResult) => { 
    // doesn't get here 
}); 

Aber es hat auch nicht funktioniert.

der Code:

1) Die Funktion 'Update', die Daten empfängt und ruft Funktion 'promiseQuery' die Daten zu verarbeiten:

const RSVP = require('rsvp'); 

let db; 

const update = (data) => {  
    let users = { 
    items: data.user, // data to be updated in db - array of user ids 
    item_type: 1, 
    id: data.department 
    } 

    let updateQueries = []; 

    // adding query promises to updateQueries 
    updateQueries.push(promiseQuery(users.id, users.item_type, users.items)); 

    RSVP.all(updateQueries).then((results) => { 

    /* here 'results' looks like that: 
     [ [ { query: 'INSERT INTO link_to_department (item_type, department, item) VALUES ($item_type, $department, $item)', 
      values: [Object] }, 
      { query: 'DELETE FROM link_to_department WHERE department = $(department) AND item_type = $(item_type) AND item=$(item)', 
      values: [Object] } ] ] 

    db update below fails with '[Empty or undefined query.]'*/ 

    db.tx((trx) => { 
     let sqlUpdates = []; 

     results.forEach((query) => { 
      sqlUpdates.push(trx.none(query.query, query.values)) 
     }) 

     return trx.batch(sqlUpdates); 
    }).then(() => { 
     res.sendStatus(204); 
    }).catch((err) => { 
     console.log('error', err.message); 
     // handle errors 
    }); 
    }); 
}; 

2) Die Funktion verarbeitet Daten 'promiseQuery' (it vergleicht Daten und Daten in db db mit den neuen Daten zu aktualisieren) erhalten:

const promiseQuery = (department_id, item_type, items) => { 
    return new RSVP.Promise((resolve, reject) => { 
     db.query('SELECT item FROM link_to_department WHERE department=' + department_id + ' AND item_type=' + item_type) 
      .then((db_items) => { 
      let promises = []; 

      let itemsToBeRemoved = []; 
      let itemsToBeAdded = []; 

      /* here we have array of user ids we received: 'items' 
       and array of user ids from db: 'db_items' */ 

      // populating 'itemsToBeAdded' and 'itemsToBeRemoved' with user ids that need to added or removed: 
      populateUpdateArray(items, db_items, itemsToBeAdded); 
      populateUpdateArray(db_items, items, itemsToBeRemoved); 

      let insert_query = 'INSERT INTO link_to_department (item_type, department, item) VALUES ($item_type, $department, $item)' 
      let delete_query = 'DELETE FROM link_to_department WHERE department = $(department) AND item_type = $(item_type) AND item=$(item)'; 

      // creating update sql queries 
      populateUpdateQuery(insert_query, itemsToBeAdded, department_id, item_type, promises); 
      populateUpdateQuery(delete_query, itemsToBeRemoved, department_id, item_type, promises); 

      RSVP.all(promises).then((results) => { 
       /* here 'results' looks like this: 
        [ { query: 'INSERT INTO link_to_department (item_type, department, item) VALUES ($item_type, $department, $item)', 
         values: { item_type: 19, department: 1, item: '1' } }, 
        { query: 'DELETE FROM link_to_department WHERE department = $(department) AND item_type = $(item_type) AND item=$(item)', 
         values: { item_type: 19, department: 1, item: 1 } }] */ 

       return resolve(results); 
      }); 

     }).catch(() => { 
      reject(); 
    }) 
    }); 
}; 

3) Diese Funktion ‚populateUpdateArray‘ auffüllt Array von Benutzer-IDs, die aktualisiert werden müssen (Basi nisch erhielten Benutzer-IDs sollten ids in der db ersetzen - für die wir überprüfen, was ids erhielten wir sind in db nicht und welche ids in db sind nicht in den empfangenen ids):

const populateUpdateArray = (array_0, array_1, updateArray) => { 
    array_0.forEach((item) => { 
     if (array_1.indexOf(item) === -1) { 
     updateArray.push(item); 
    } 
    }); 
}; 

4) diese Funktion ‚populateUpdateQuery 'sql update Abfragen:

const populateUpdateQuery = (query, id_array, department_id, item_type, promises) => { 
    return new RSVP.Promise((resolve, reject) => { 
    id_array.forEach((item) => { 
     let values = { 
      item_type: item_type, 
      department: department_id, 
      item: item 
     }; 

     promises.push({query, values}); 
    }); 

    resolve(promises);  
    }); 
}; 

Vielen Dank!

EDIT: änderte ich den Code nur eine DB-Verbindung zu haben und ich den Code ein wenig vereinfacht. Ich bekomme keine Fehler, aber Abfragen werden immer noch nicht ausgeführt. Ich glaube ich vermisse hier etwas Grundlegendes:

const update = (data) => { 
    let users = { 
     items: data.user, 
     item_type: 1, 
     id: data.department 
    } 

    db.tx((tx) => { 
     let updateQueries = []; 

     updateQueries.push(promiseQuery(department.id, users.item_type, users.items, tx)); 

     RSVP.all(updateQueries).then((results) => { 
      // results is array of array, so i flatten it 
      let sqlUpdates = results.reduce((a, b) => { return a.concat(b); }, []); 

      /* sqlUpdates here: 
      [ Promise { 
       _bitField: 0, 
       _fulfillmentHandler0: undefined, 
       _rejectionHandler0: undefined, 
       _promise0: undefined, 
       _receiver0: undefined } ] 
      */ 

      return tx.batch(sqlUpdates); 
     }); 
    }).then(() => { 
     res.sendStatus(204); 
    }).catch((err) => { 
     console.log('error', err.message); 
    }); 
}; 

const promiseQuery = (department_id, item_type, items, tx) => { 
    return new RSVP.Promise((resolve, reject) => { 
    tx.query('SELECT item FROM belongs_to_departments WHERE department=' + department_id + ' AND item_type=' + item_type) 
     .then((db_items)=> { 
      let queries = [];    
      let itemsToBeAdded = []; 
      let insert_query = 'INSERT INTO belongs_to_departments (item_type, department, item) VALUES ($(item_type), $(department), $(item))'; 

      populateUpdateArray(items, db_items, itemsToBeAdded); 
      populateUpdateQuery(insert_query, itemsToBeAdded, department_id, item_type, queries, tx); 

      resolve(queries); 
     }).catch(() => { 
      reject(); 
     }); 
    }); 
}; 

const populateUpdateArray = (array_0, array_1, updateArray) => { 
    array_0.forEach((item) => { 
    if (array_1.indexOf(item) === -1) { 
     updateArray.push(item); 
    } 
    }); 
}; 

const populateUpdateQuery = (query, id_array, department_id, item_type, queries, tx) => { 
    id_array.forEach((item) => { 
     let values = { 
      item_type: item_type, 
      department: department_id, 
      item: item 
     }; 

     queries.push(tx.none(query, values)); 
    }); 
}; 
+0

Es ist in dem folgenden gemeinsamen Fehler erklärt: [Aufgaben im Vergleich zu root/direkten Abfragen] (https://github.com/vitaly-t/pg-promise/wiki/Common- Fehler # tasks-versus-rootdirect-Abfragen) –

+0

danke mate, ist nicht "der richtige Weg, es zu tun" aus dem Link genau das, was ich in "update" -Funktion mit db.tx (für alle einfügen/löschen Abfragen) tun? meinst du besser ich schließe ein 1) wähle aus, dass ich in 'sponsorQuery' und 2) alle diese einfüge/lösche anfragen in eine task/tx? –

+0

Es ist verwirrend, warum Ihre Funktion 'populateUpdateQuery' Versprechungen verwendet, während sie nicht einmal asynchron ist ... So viel wird nun ausgeführt, um es aus separaten Teilen herauszuarbeiten. Im Allgemeinen sollten Sie alle Ihre Abfragen innerhalb einer einzelnen Aufgabe/Transaktion ausführen. –

Antwort

0

Danke an Vitaly für die Hilfe. die für mich gearbeitet:

const update = data => { 
    const users = { 
     items: data.user, 
     item_type: 1, 
     id: data.department 
    } 

    db.tx(tx => { 
     const updateQueries = []; 

     updateQueries.push(promiseQuery(department.id, users.item_type, users.items, tx)); 

     RSVP.all(updateQueries).then(results => { 
      // results is array of array, so i flatten it 
      const sqlUpdates = results.reduce((a, b) => { return a.concat(b); }, []);       

      return tx.batch(sqlUpdates); 
     }); 
    }).then(() => { 
     res.sendStatus(204); 
    }).catch(err => { 
     console.log('error', err.message); 
    }); 
}; 

const promiseQuery = (department_id, item_type, items, tx) => { 
    return new RSVP.Promise((resolve, reject) => { 
    tx.query('SELECT item FROM belongs_to_departments WHERE department=' + department_id + ' AND item_type=' + item_type) 
     .then(db_items => { 
      const queries = [];    
      const itemsToBeAdded = []; 
      const insert_query = 'INSERT INTO belongs_to_departments (item_type, department, item) VALUES ($(item_type), $(department), $(item))'; 

      populateUpdateArray(items, db_items, itemsToBeAdded); 
      populateUpdateQuery(insert_query, itemsToBeAdded, department_id, item_type, queries, tx); 

      resolve(queries); 
     }).catch(() => { 
      reject(); 
     }); 
    }); 
}; 

const populateUpdateArray = (array_0, array_1, updateArray) => { 
    array_0.forEach((item) => { 
    if (array_1.indexOf(item) === -1) { 
     updateArray.push(item); 
    } 
    }); 
}; 

const populateUpdateQuery = (query, id_array, department_id, item_type, queries, tx) => { 
    id_array.forEach(item => { 
     const values = { 
      item_type: item_type, 
      department: department_id, 
      item: item 
     }; 

     queries.push(tx.none(query, values)); 
    }); 
}; 
+0

Sie dürfen 'RSVP.all' niemals verwenden, um Abfragen zu lösen, es wird nicht gut für den Fall funktionieren eines Fehlers. Sie müssen nur die Methode 'batch' verwenden, um Arrays von Abfragen aufzulösen;) Sehen Sie sich dies an: https://github.com/vitaly-t/pg-promise/wiki/Common-Mistakes#tasks-versus-rootdirect-queries –

Verwandte Themen