摘要:我想應該會有很多像我一樣的前端聽說可以開發后臺時,激動地踏上了之路,這條路上第一個挑戰,就是回調地獄。
我想應該會有很多像我一樣的前端聽說js可以開發后臺時,激動地踏上了node.js之路,這條路上第一個挑戰,就是回調地獄。
app.get("/changePassword?**",function(req,res){ if(req.cookies.username){ pool.getConnection(function(err,connection){ if (err) { console.log(err+"--from pool connection"); res.send("修改密碼失敗,數據庫連接錯誤"); } else{ connection.query("USE userInfo",function(err,rows){ if (err) { console.log(err+"--from using database"); res.send("修改密碼失敗,數據庫使用錯誤"); } else{ var selectQuery = "SELECT * FROM users WHERE userName="+"""+req.cookies.username+"""; connection.query(selectQuery,function(err,rows){ if (err) { console.log(err+"--from selectQuery"); res.send("修改密碼失敗,數據庫查詢錯誤"); } else{ if (req.query.password==rows[0].password) { var updateQuery = "UPDATE users SET password="+"""+req.query.newPassword+"" WHERE username="+"""+req.cookies.username+"""; connection.query(updateQuery,function(err,rows){ if (err) { console.log(err+"--from updateQuery"); res.send("修改密碼失敗,數據庫更新錯誤"); } else{ res.send("修改密碼成功"); } });/*connection.query update end*/ } else{ res.send("修改密碼失敗,原始密碼錯誤"); } } });/*connection.query select end*/ } });/*connection.query using database end*/ } if(connection){connection.release()}; });/*pool.getConnection end*/ } else { res.send("修改密碼失敗,登錄失效"); } });/*app.get end*/
這種造型的代碼就是“邪惡金字塔”,或者說“回調地獄”,callback hell
我遇到的第一個障礙就是它,它讓代碼難以維護,難以修改,橫向發展,非常不美觀
于是我開始試圖解決這個問題,為此,我求助了很多大神,看了很多帖子,被告知《ES6入門》這本書可以解決我的問題,于是從promise then到*yield到async/await
看到async/await我以為就皆大歡喜,問題解決了,然而nodejs目前需要babel轉碼才能使用async/await,很麻煩,而且對我這個新手很不友好。
在segmentfault上提問許久,發現有個asyncawait模塊,可以模仿async/await模型來操作promise對象
npm install asyncawait
將如下代碼添加到你的js文件中
var async = require("asyncawait/async"); var await = require("asyncawait/await"); var foo = async (function() { var resultA = await (firstAsyncCall()); var resultB = await (secondAsyncCallUsing(resultA)); var resultC = await (thirdAsyncCallUsing(resultB)); return doSomethingWith(resultC); });
await()里面可以放promise對象,也可以放異步回調函數,只要它有類似的返回機制,這樣一來,就能提前使用async/await模式寫代碼了,一開始的回調地獄會變得如下代碼一樣,清晰易懂
//登錄路由 app.get("/loginForm?**", async(function(req, res) { try { var connection = await(poolp.getConnection()); var selectQuery = "SELECT password FROM users WHERE username ="" + req.query.username + """; var rows = await(connection.query(selectQuery)); if (rows.length == 0) throw "登錄失敗,用戶不存在"; if (rows[0].password != req.query.password) { throw "登錄失敗,密碼不正確"; } else { res.send("登錄成功"); } } catch (err) { res.send(err); } //記得釋放connection,不然很快就會達到上限 if(connection) pool.releaseConnection(connection); }));
不幸的是,await()里面放回調函數會使得代碼很臃腫,如果放promise對象,就保持了與async/await模式的一致性。
nodejs的mysql模塊,提供了pool,connection來操作數據庫,可是它們都不是promise對象,我嘗試自己封裝成promise對象
var getConn = new Promise(function(resolve,reject){ pool.getConnection(function(err,connection){ if (err) { reject(err); } else { resolve(connection); } }); }); var DBobj = function(connection){ this.connection = connection; this.query = (queryString)=>{ var connPromise = new Promise(function(resolve, reject) { this.connection.query(queryString, function(err, rows) { if (err) { reject(err); } else { resolve(rows); } }); }); return connPromise; }; return this; };
很蛋疼,而且DBobj無法正確返回對象,不過國外有大神早就解決了這個問題
npm install promise-mysql
var mysqlp = require("promise-mysql"); poolp = mysqlp.createPool({ host: "localhost", user: "root", password: "root", database: "userInfo", connectionLimit: 10 });
就這么將mysql提供的對象轉化為了promise對象,于是上面的登錄路由就可以運行了,簡潔明了,要加正則或者別的什么驗證隨時都能加,只需要在兩行代碼之間插入邏輯,再也不用框起一大片代碼然后調縮進了!
相應的,fs模塊,mail模塊也應該有promise版本,大家可以去npm上面搜索
最后,我希望我的文章能幫助像我一樣的小白打敗回調地獄,一起踏上nodejs的探索之旅
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78864.html
摘要:最簡單的監聽辦法就是使用使用格式如下它有兩個參數,第一個參數是指定的單個按鍵或者組合鍵,第二個參數是一個回調函數,它在每一次用戶按下指定的時被調用。 keypress.js是一個捕獲鍵盤輸入的JavaScript庫,它簡單易用,輕量級的壓縮版本只有9kB左右,并且沒有依賴其他JavaScript庫。 我們通常用鍵盤事件來監聽keydown和keyup事件。當按下鍵盤的任意鍵的時候,ke...
摘要:年終總結結果到這個時間才寫,其實也是無奈。這一年最重要的事情就是順利從一只學生狗轉職為一只社畜。四月份畢業之后以前端工程師的職位入職天貓,到現在也差不多工作一年了。 年終總結結果到這個時間才寫,其實也是無奈。本來計劃過年寫的,沒想到Steam竟然開了個農歷春節特惠,然后就被各種游戲打了,辣雞平臺,斂我錢財,頹我精神,耗我青春,害我單身 以下全都是個人看法,如果有不認同的地方,請大吼一聲...
摘要:年終總結結果到這個時間才寫,其實也是無奈。這一年最重要的事情就是順利從一只學生狗轉職為一只社畜。四月份畢業之后以前端工程師的職位入職天貓,到現在也差不多工作一年了。 年終總結結果到這個時間才寫,其實也是無奈。本來計劃過年寫的,沒想到Steam竟然開了個農歷春節特惠,然后就被各種游戲打了,辣雞平臺,斂我錢財,頹我精神,耗我青春,害我單身 以下全都是個人看法,如果有不認同的地方,請大吼一聲...
摘要:什么是回調地獄異步代碼,或者說使用的代碼,很難符合我們的直觀理解。人們理解回調的最大障礙在于理解一個程序的執行順序。怎樣解決回調地獄問題糟糕的編碼習慣造成了回調地獄。把回調函數的第一個參數設置為對象,是中處理異常最流行的方式。 什么是回調地獄? 異步Javascript代碼,或者說使用callback的Javascript代碼,很難符合我們的直觀理解。很多代碼最終會寫成這樣: fs.r...
摘要:類的適配器結構目標角色這就是所期待得到的接口,由于是類適配器模式,因此目標不可以是類。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。和適配器模式的關系適配器模式的用意是改變所考慮對象的接口,而代理模式不能改變。 點擊進入我的博客 3.1 適配器模式 適配器模式把一個類的接口變換成客戶端所期待的另一種接口,使得原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。 3...
閱讀 2620·2021-10-12 10:12
閱讀 778·2019-08-29 17:25
閱讀 2782·2019-08-29 17:24
閱讀 3204·2019-08-29 17:19
閱讀 1792·2019-08-29 15:39
閱讀 3031·2019-08-26 16:50
閱讀 1984·2019-08-26 12:17
閱讀 2694·2019-08-26 12:16