日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

COMBO--组合拳打穿回调地狱~

發布時間:2023/12/15 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 COMBO--组合拳打穿回调地狱~ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我想應該會有很多像我一樣的前端聽說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的探索之旅

總結

以上是生活随笔為你收集整理的COMBO--组合拳打穿回调地狱~的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。