JavaScript异步编程1.5 嵌套式回调的解嵌套_JavaScript异步编程1.5 嵌套式回调的解嵌套试读-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > JavaScript异步编程 > 1.5 嵌套式回调的解嵌套

JavaScript异步编程——1.5 嵌套式回调的解嵌套

JavaScript中最常见的反模式做法是,回调内部再嵌套回调。还记得前言里提到的金字塔厄运吗?我们先来看一个具体的例子,你也可能在Node服务器上看到过类似的代码。 function checkPassword(username, passwordGuess, callback) { var queryStr = 'SELECT * FROM user WHERE username = ?'; db.query(queryStr, username, function (err, result) { if (err) throw err; hash(passwordGuess, function(passwordGuessHash) { callback(passwordGuessHash === result['password_hash']); }); }); } 这里定义了一个异步函数checkPassword,它触发了另一个异步函数db.query,而后者又可能触发另外一个异步函数hash。(在阅读代码之前,无法确认这些函数是否真的异步,但这里的几个函数理应如此。) 这段代码有什么问题呢?目前为止,没有任何问题。它能用,而且简洁明了。但是,如果试图向其添加新特性,它就会变得毛里毛躁、险象环生,比如去处理那个数据库错误,而不是抛出错误(请参阅1.4.3节)、记录尝试访问数据库的次数、阻塞访问数据库,等等。 嵌套式回调诱惑我们通过添加更多代码来添加更多特性,而不是将这些特性实现为可管理、可重用的代码片段。checkPassword有一种可以避免出现上述苗头的等价实现方式,如下: function checkPassword(username, passwordGuess, callback) { var passwordHash; var queryStr = 'SELECT * FROM user WHERE username = ?'; db.query(qyeryStr, username, queryCallback); function queryCallback(err, result) { if (err) throw err; passwordHash = result['password_hash']; hash(passwordGuess, hashCallback); } function hashCallback(passwordGuessHash) { callback(passwordHash === passwordGuessHash); } } 这种写法更啰嗦一些,但读起来更清晰,也更容易扩展。由于这里赋予了异步结果(即passwordHash)更宽广的作用域,所以获得了更大的灵活性。 按照惯例,请避免两层以上的函数嵌套。关键是找到一种在激活异步调用之函数的外部存储异步结果的方式,这样回调本身就没有必要再嵌套了。 如果这样听起来有点诘聱难懂,请别担心。我们在后续几章中会看到大量的异步事件例子,那里的异步事件顺序运行且没有嵌套式事件处理器。

展开全文

推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

《JavaScript异步编程》其他试读目录

• 第1章:深入理解JavaScript事件
• 1.1.1 现在还是将来运行
• 1.1.2 线程的阻塞
• 1.1.3 队列
• 1.2 异步函数的类型
• 1.2.1 异步的I/O函数
• 1.2.2 异步的计时函数
• 1.3 异步函数的编写
• 1.3.1 何时称函数为异步的
• 1.3.2 间或异步的函数
• 1.3.3 缓存型异步函数
• 1.3.4 异步递归与回调存储
• 1.3.5 返值与回调的混搭
• 1.4 异步错误的处理
• 1.4.1 回调内抛出的错误
• 1.4.2 未捕获异常的处理
• 1.4.3 抛出还是不抛出
• 1.5 嵌套式回调的解嵌套 [当前]
• 1.6 小结