理解JavaScript的回调机制
原文:Understanding Callbacks in JavaScript
“回调”是JavaScript中较其他语言不同的几个概念之一。本文围绕回调帮助你缕清思路。
JavaScript常见的回调模式,是把内联函数作为参数传递给另一个函数。例如:
1 | [1, 2, 3].forEach(function callback(v) { |
最直观的讲,JavaScript的回调不是你主动调用,而是由其他代码调用的函数。“其他代码”可能是JavaScript的内置函数,比如setTimeout()
;可能是一个框架,比如Express
;可能是一个库,比如axios
;可能是任何JavaScript中的代码。回调是响应式的,而非命令式的:你定义一个函数,它会在另一块代码中调用,但你不对调用这个函数负责。
1 | // JavaScript运行时负责在5秒后调用 `callback` |
Node风格回调
Promise相对较晚加入JavaScript,首次加入在2015年。在Promise和async/await之前,Node.js中事实标准的异步操作范例,是传递一个回调函数,带2个参数,一个错误err和一个结果res。当说到“回调地狱”时,其实说的就是Node风格的回调。
例如,亚马逊AWS S3的Node.js SDK只支持回调。为了实现上传文件完成时发起提醒,需要传递一个回调函数。
1 | const AWS = require('aws-sdk'); |
Node风格回调的主要作用,是告诉你一个异步操作成功或失败,如果成功,结果是什么。Promise在这个方面已经取代了Node风格回调,因为嵌套的回调在语法上非常令人难受,而且Node风格的回调从未形成标准化。
回调转换为Promise
Node.js内置了promisify()函数,可以把基于回调的API转换成Promise风格。使用promisify()将一个基于Node回调的函数,转换为一个返回Promise的函数,如下例:
1 | function myCallbackBasedFunction(callback) { |