1

我是 Promise 的新手,我正在尝试在 Node.js 和 PostgreSQL 中使用 RSVP Promise,但我做错了,很可能。任何有关如何解决该问题或如何改进代码的建议都值得赞赏。

我试图实现的是:接收数据后 - 处理数据以创建 SQL 更新查询,并在它们准备好时 - 执行它们。这里的数据是用户 ID 数组。

什么不起作用:我得到了一系列无法​​解决的承诺数组,我尝试像这样解决数组:

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

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

但它也没有奏效。

编码:

1)接收数据并调用函数'promiseQuery'处理数据的函数'update':

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)函数'promiseQuery'处理数据(它比较接收到的数据和db中的数据以用新数据更新db):

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)该函数'populateUpdateArray'填充需要更新的用户ID数组(基本上,接收到的用户ID应该替换数据库中的ID - 因为我们检查我们收到的哪些ID不在数据库中,哪些ID不在数据库中收到的ID):

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

4) 该函数“populateUpdateQuery”返回 sql 更新查询:

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);      
  });
};

谢谢!

编辑:我将代码更改为只有一个数据库连接,并稍微简化了代码。我没有收到任何错误,但仍然没有执行查询。我想我在这里缺少一些基本的东西:

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));
   });
};
4

1 回答 1

0

感谢维塔利的帮助。这对我有用:

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));
   });
};
于 2016-12-09T09:22:39.317 回答