2016-10-16 279 views
0

我正在建設一個帶有NodeJS後端的網上商店。 我有承諾,從數據庫中選擇USER_ID的令牌,然後我做的另一個選擇從特定用戶獲取購物車數據:JavaScript承諾錯誤返回

function selectItemsFromCart(userToken){ 
    return new Promise(function(resolve, reject){ 
    var queryString = "SELECT id FROM users WHERE token='"+userToken.token+"'"; 
    return dbconn.query(queryString, function(err, res){ 
     if(err){ 
     reject(err); 
     } 
     var userId = res[0].id; 
     resolve(userId); 
    }); 
    }).then(function(userId){ 
    var queryString = "SELECT * FROM cart LEFT JOIN users ON cart.user_id='"+userId+"'"; 
    return dbconn.query(queryString, function(err,res){ 
     if(err){ 
     return err; 
     } 
     return res; 
    }); 
    }); 
} 

當我試圖把它送回來給前是這樣的:

app.use('/showCartItems', function(req, res){ 
    selectItemsFromCart(req.body).then(function(result){ 
    console.log(result); 
    res.send(result); 
    }).catch(function(err){ 
    res.status(500).end("Can't load cart"); 
    }); 
}); 

我的控制檯,而不是顯示我一起的結果,它顯示了這個查詢日誌:

Query { 
    domain: null, 
    _events: 
    { error: [Function], 
    packet: [Function], 
    end: [Function], 
    timeout: [Function], 
    'start-tls': [Function] }, 
    _eventsCount: 5, 
    _maxListeners: undefined, 
    _callback: [Function], 
    _callSite: 
    Error 
     at Protocol._enqueue (/var/www/html/Web Shop Yoon/src/node_modules/mysql/lib/protocol/Protocol.js:141:48) 
     at Connection.query (/var/www/html/Web Shop Yoon/src/node_modules/mysql/lib/Connection.js:214:25) 
     at /var/www/html/Web Shop Yoon/src/script.js:155:19 
     at process._tickCallback (internal/process/next_tick.js:103:7), 
    _ended: false, 
    _timeout: undefined, 
    _idleNext: null, 
    _idlePrev: null, 
    _idleStart: null, 
    _idleTimeout: -1, 
    _repeat: null, 
    sql: 'SELECT * FROM cart LEFT JOIN users ON cart.user_id=\'15\'', 
    values: undefined, 
    typeCast: true, 
    nestTables: false, 
    _resultSet: null, 
    _results: [], 
    _fields: [], 
    _index: 0, 
    _loadError: null, 
    _connection: 
    Connection { 
    domain: null, 
    _events: {}.... 

我怎樣才能得到我的承諾的權利返還?

+1

你正確使用'你的第一個'query'回調reject' /'resolve',但在你的第二個'query'回調中,你使用'return'來代替。爲什麼?你期望這些返回值用於什麼? 'query'肯定不會(並且不能)返回它們。 –

+1

dbconn.query是異步的,不會返回一個Promise,因此你不能像這樣使用它......你似乎已經爲第一個dbconn.query做了正確的事情,你只是「忘記」包裝第二個一個在Promise中 - 我建議爲dbconn.query創建一個包裝函數來Promisify它 –

+0

備註:您在客戶端上使用Angular的事實與您的問題完全無關,並且可能讓讀者感到困惑(請參閱[這個答案嘗試](​​http://stackoverflow.com/a/40069350/157247),例如,錯誤客戶端代碼的引用代碼)。由於這是純粹的服務器端,因此我會建議完全關閉Angular的事情(並相應地編輯了這個問題)。 –

回答

3

你只是沒有完全承諾,代碼。您首次使用query的承諾沒有問題(除return之外沒有任何作用),但是您沒有完全將其應用到第二個承諾中。

除此之外:

  1. 至少有一個表面上的SQL注入風險,以及相當可能有兩個,在代碼;雖然你可能從上下文知道沒有風險,但仍然通常值得使用API​​的功能來防禦它。

  2. 當您在第一query,你在做reject(err);取回一個錯誤(這是正確的)使用res[0].id,這很可能被拋出異常,如果resundefinednull但隨後繼續到代碼(它可能是)。雖然這是相對無害(例外將被轉換爲拒絕,將被忽略,因爲以前的拒絕已經到位),這絕對是不正確的。 :-)你想在那裏有一個else

看評論:

function selectItemsFromCart(userToken) { 
    return new Promise(function(resolve, reject) { 
     var queryString = "SELECT id FROM users WHERE token='" + userToken.token + "'"; 
     // WARNING!! SQL INJECTION RISK!! ------------------^^^^^^^^^^^^^^^^^^^^^^^^^ 
     dbconn.query(queryString, function(err, res) { // Note: No return on this line, it's not used for anything 
      if (err) { 
       reject(err); 
      } else {     // Note else 
       var userId = res[0].id; 
       resolve(userId); 
      } 
     }); 
    }).then(function(userId) { 
     // Note use of a new promise 
     return new Promise(function(resolve, reject) { 
      var queryString = "SELECT * FROM cart LEFT JOIN users ON cart.user_id='" + userId + "'"; 
      // WARNING!! Potential SQL INJECTION RISK!! --------------------------^^^^^^^^^^^^^^^^ 
      dbconn.query(queryString, function(err, res) { 
       if (err) { 
        reject(err); 
       } else { 
        resolve(res); 
       } 
      }); 
     }); 
    }); 
} 

或者,也有圖書館有使用的NodeJS樣式的回調與err, response說法對,採取的API並將它們轉換成承諾,指明分數的API來代替,處理這種管道爲你。


重新SQL注入的警告,請參閱http://bobby-tables.com這不朽的漫畫:

enter image description here

+1

另外我會改變'if(err){reject(err);如果(錯誤)返回拒絕(錯誤);'調用拒絕不退出函數。 – Keith

+0

@Keith:我剛剛看到了這一點,並將其標記出來(儘管使用了不同的解決方案)。接得好。 –

+0

我剛剛重讀了代碼:p –