2016-11-28 160 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 –