2016-11-28 98 views
1

我是承诺的新手,我试图在Node.js中使用PostgreSQL中的RSVP承诺,我做错了,最有可能的。 有关如何解决该问题或如何改进代码的任何建议,都将受到赞赏。解析承诺数组node.js

我试图实现的是:在接收数据之后 - 处理数据以创建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' 处理数据(它在分贝接收的数据和数据进行比较用新的数据来更新分贝):

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的数组(BASI凯莉,接收到的用户ID应该在DB取代IDS - 为我们检查收到什么ID不以dB为单位,什么IDS以dB为单位是不是在接收IDS):

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

它在下列常见的错误解释:任务与根/直接查询](https://github.com/vitaly-t/pg-promise/wiki/Common-错误#tasks-versus-rootdirect-queries) –

+0

感谢队友,是不是“正确的方式做到这一点”的链接正是我所做的与db.tx(更新)功能(所有插入/删除查询)?你的意思是我最好包括1)选择我在'promiseQuery'和2)所有这些插入/删除查询到一个任务/ TX? –

+0

令人困惑的是,为什么你的函数'populateUpdateQuery'全部使用promise,而它甚至不是异步的...因此,我们正在从单独的部分开始工作。一般来说,是的,您应该在单个任务/事务中执行所有查询。 –

回答

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

您绝对不能使用RSVP.all来解决查询,否则它将无法正常工作的错误。您只能使用'batch'方法来解析查询数组;}看看这个:https://github.com/vitaly-t/pg-promise/wiki/Common-Mistakes#tasks-versus-rootdirect-queries –