成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

COMBO--組合拳打穿回調(diào)地獄~

aristark / 3091人閱讀

摘要:我想應(yīng)該會有很多像我一樣的前端聽說可以開發(fā)后臺時(shí),激動地踏上了之路,這條路上第一個(gè)挑戰(zhàn),就是回調(diào)地獄。

我想應(yīng)該會有很多像我一樣的前端聽說js可以開發(fā)后臺時(shí),激動地踏上了node.js之路,這條路上第一個(gè)挑戰(zhàn),就是回調(diào)地獄。

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("修改密碼失敗,數(shù)據(jù)庫連接錯(cuò)誤");
                    } else{
                        connection.query("USE userInfo",function(err,rows){
                            if (err) {
                                console.log(err+"--from using database");
                                res.send("修改密碼失敗,數(shù)據(jù)庫使用錯(cuò)誤");
                            } 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("修改密碼失敗,數(shù)據(jù)庫查詢錯(cuò)誤");
                                    } 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("修改密碼失敗,數(shù)據(jù)庫更新錯(cuò)誤");
                                                } else{
                                                    res.send("修改密碼成功");
                                                }
                                            });/*connection.query update end*/
                                        } else{
                                            res.send("修改密碼失敗,原始密碼錯(cuò)誤");
                                        }
                                    }
                                });/*connection.query select end*/
                            }
                        });/*connection.query using database end*/
                    }
                    if(connection){connection.release()};
                });/*pool.getConnection end*/
        } else {
            res.send("修改密碼失敗,登錄失效");
        }
    });/*app.get end*/

    

這種造型的代碼就是“邪惡金字塔”,或者說“回調(diào)地獄”,callback hell
我遇到的第一個(gè)障礙就是它,它讓代碼難以維護(hù),難以修改,橫向發(fā)展,非常不美觀
于是我開始試圖解決這個(gè)問題,為此,我求助了很多大神,看了很多帖子,被告知《ES6入門》這本書可以解決我的問題,于是從promise then到*yield到async/await
看到async/await我以為就皆大歡喜,問題解決了,然而nodejs目前需要babel轉(zhuǎn)碼才能使用async/await,很麻煩,而且對我這個(gè)新手很不友好。
在segmentfault上提問許久,發(fā)現(xiàn)有個(gè)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對象,也可以放異步回調(diào)函數(shù),只要它有類似的返回機(jī)制,這樣一來,就能提前使用async/await模式寫代碼了,一開始的回調(diào)地獄會變得如下代碼一樣,清晰易懂

//登錄路由
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,不然很快就會達(dá)到上限
    if(connection) pool.releaseConnection(connection);
}));

不幸的是,await()里面放回調(diào)函數(shù)會使得代碼很臃腫,如果放promise對象,就保持了與async/await模式的一致性。
nodejs的mysql模塊,提供了pool,connection來操作數(shù)據(jù)庫,可是它們都不是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無法正確返回對象,不過國外有大神早就解決了這個(gè)問題

npm install promise-mysql

var mysqlp = require("promise-mysql");
poolp = mysqlp.createPool({
  host: "localhost",
  user: "root",
  password: "root",
  database: "userInfo",
  connectionLimit: 10
});

就這么將mysql提供的對象轉(zhuǎn)化為了promise對象,于是上面的登錄路由就可以運(yùn)行了,簡潔明了,要加正則或者別的什么驗(yàn)證隨時(shí)都能加,只需要在兩行代碼之間插入邏輯,再也不用框起一大片代碼然后調(diào)縮進(jìn)了!

相應(yīng)的,fs模塊,mail模塊也應(yīng)該有promise版本,大家可以去npm上面搜索

最后,我希望我的文章能幫助像我一樣的小白打敗回調(diào)地獄,一起踏上nodejs的探索之旅

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78864.html

相關(guān)文章

  • 用來捕獲鍵盤輸入的keypress.js介紹

    摘要:最簡單的監(jiān)聽辦法就是使用使用格式如下它有兩個(gè)參數(shù),第一個(gè)參數(shù)是指定的單個(gè)按鍵或者組合鍵,第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),它在每一次用戶按下指定的時(shí)被調(diào)用。 keypress.js是一個(gè)捕獲鍵盤輸入的JavaScript庫,它簡單易用,輕量級的壓縮版本只有9kB左右,并且沒有依賴其他JavaScript庫。 我們通常用鍵盤事件來監(jiān)聽keydown和keyup事件。當(dāng)按下鍵盤的任意鍵的時(shí)候,ke...

    cuieney 評論0 收藏0
  • 本命年一定要記得穿紅褲衩:2015年總結(jié)

    摘要:年終總結(jié)結(jié)果到這個(gè)時(shí)間才寫,其實(shí)也是無奈。這一年最重要的事情就是順利從一只學(xué)生狗轉(zhuǎn)職為一只社畜。四月份畢業(yè)之后以前端工程師的職位入職天貓,到現(xiàn)在也差不多工作一年了。 年終總結(jié)結(jié)果到這個(gè)時(shí)間才寫,其實(shí)也是無奈。本來計(jì)劃過年寫的,沒想到Steam竟然開了個(gè)農(nóng)歷春節(jié)特惠,然后就被各種游戲打了,辣雞平臺,斂我錢財(cái),頹我精神,耗我青春,害我單身 以下全都是個(gè)人看法,如果有不認(rèn)同的地方,請大吼一聲...

    AlienZHOU 評論0 收藏0
  • 本命年一定要記得穿紅褲衩:2015年總結(jié)

    摘要:年終總結(jié)結(jié)果到這個(gè)時(shí)間才寫,其實(shí)也是無奈。這一年最重要的事情就是順利從一只學(xué)生狗轉(zhuǎn)職為一只社畜。四月份畢業(yè)之后以前端工程師的職位入職天貓,到現(xiàn)在也差不多工作一年了。 年終總結(jié)結(jié)果到這個(gè)時(shí)間才寫,其實(shí)也是無奈。本來計(jì)劃過年寫的,沒想到Steam竟然開了個(gè)農(nóng)歷春節(jié)特惠,然后就被各種游戲打了,辣雞平臺,斂我錢財(cái),頹我精神,耗我青春,害我單身 以下全都是個(gè)人看法,如果有不認(rèn)同的地方,請大吼一聲...

    xi4oh4o 評論0 收藏0
  • 回調(diào)地獄-編寫異步JavaScript指南

    摘要:什么是回調(diào)地獄異步代碼,或者說使用的代碼,很難符合我們的直觀理解。人們理解回調(diào)的最大障礙在于理解一個(gè)程序的執(zhí)行順序。怎樣解決回調(diào)地獄問題糟糕的編碼習(xí)慣造成了回調(diào)地獄。把回調(diào)函數(shù)的第一個(gè)參數(shù)設(shè)置為對象,是中處理異常最流行的方式。 什么是回調(diào)地獄? 異步Javascript代碼,或者說使用callback的Javascript代碼,很難符合我們的直觀理解。很多代碼最終會寫成這樣: fs.r...

    劉玉平 評論0 收藏0
  • 《設(shè)計(jì)模式》3.結(jié)構(gòu)型模式

    摘要:類的適配器結(jié)構(gòu)目標(biāo)角色這就是所期待得到的接口,由于是類適配器模式,因此目標(biāo)不可以是類。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它是作為現(xiàn)有的類的一個(gè)包裝。和適配器模式的關(guān)系適配器模式的用意是改變所考慮對象的接口,而代理模式不能改變。 點(diǎn)擊進(jìn)入我的博客 3.1 適配器模式 適配器模式把一個(gè)類的接口變換成客戶端所期待的另一種接口,使得原本因接口不匹配而無法在一起工作的兩個(gè)類能夠在一起工作。 3...

    Yuqi 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<