我是承诺的新手,我正在尝试使用PostgreSQL在Node.js中使用RSVP承诺而且我做错了,很可能。 有关如何解决该问题或如何改进代码的任何建议都表示赞赏。
我尝试实现的是:在接收数据之后 - 处理数据以创建SQL更新查询以及何时准备好 - 执行它们。这里的数据是用户ID数组。
什么行不通:我获得了一系列无法解决的承诺,我试图像这样解决数组:
var promise4all = RSVP.all(
updateQueries.map((innerPromiseArray) => {
return RSVP.all(innerPromiseArray);
})
);
promise4all.then((promiseGroupResult) => {
// doesn't get here
});
但它也没有用。
代码:
1)功能'更新'接收数据和调用函数' promiseQuery'处理数据:
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应该替换db中的ID - 因为我们检查我们收到的ID不在db中,db中的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 update queries:
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));
});
};
答案 0 :(得分:0)
感谢Vitaly的帮助。 这对我有用:
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));
});
};