核心内容摘要
解锁肌密:日本“猛猛猛”护肤品,让你美到“原地爆炸”!
1 概述回调函数就是作为一个函数的参数的函数在外部函数执行完毕的时候这个回调函数会在特定的时机执行。
通常在同步或者异步的编程场景下要用到异步编程的时候可以用promise 或者 async/await 定时器setTimeout这些时间相关的api。
回调地狱就是原生回调函数们不断嵌套嵌套嵌套像俄罗斯套娃一样虽然实现了按照一定顺序的输出但是由于层层嵌套难以维护不好调试和复用。
这个时候避免回调地狱用的就是promise .then 看起来就是链式调用then 然后在这个基础上有一个async / await 语法糖 写起来更简洁看起来像同步编程的代码一样。
这两种方式都避免了回调地狱代码复用性和可读性更好。
2 回调函数简单来说回调函数就是一个被作为参数传递给另一个函数的函数并且这个被传递的函数在外部函数执行完毕后的某个时机被“回调”执行。
回调函数是作为参数传递到另一个函数中然后在外部函数内调用以完成某种例行程序或操作的函数。
JavaScript 回调函数 | 全栈开发回调函数 - MDN Web 文档术语表Web 相关术语的定义 | MDN你需要先定义doSomething函数或者使用已有的异步API如setTimeout、Promise等才能正常运行这段代码。
WindowsetTimeout() 方法 - Web API | MDN如果你的doSomething是同步的let value 1; function doSomething(callback) { callback(); // 同步执行回调 } doSomething(() { value 2; }); console.log(value); // 输出: 2如果你的doSomething是异步的比如使用setTimeoutlet value 1; function doSomething(callback) { setTimeout(callback,
; // 异步执行回调 } doSomething(() { value 2; }); console.log(value); // 输出: 1因为回调函数还没有执行最常见的实际例子let value 1; // 模拟异步操作 setTimeout(() { value 2; console.log(回调中:, value); // 最后输出: 回调中: 2 },
; console.log(当前:, value); // 先输出: 当前: 1关键点同步代码立即执行console.log会在回调函数执行后执行异步代码如setTimeout、Promise、fetch等会将回调放入事件队列等待主线程空闲时执行在异步情况下console.log会在回调函数执行前执行3 回调地狱Callback Hell一文告诉你什么是回调地狱如何解决回调地狱-CSDN博客虽然回调函数是处理异步的基础但在实际开发中如果存在多个相互依赖的异步操作就可能导致回调函数层层嵌套。
每一层异步操作都需要在前一层操作的回调函数内部发起形成所谓的“回调地狱”Callback Hell或“毁灭金字塔”Pyramid of Doom。
回调地狱呢回调函数里面一直嵌套回调函数类似于定时器里面一直嵌套setTimeout如果需要执行很多轮呢这么就是陷入了回调地狱代码可读性很差也不好维护 。
例子定时器层层嵌套// 回调地狱版本定时器层层嵌套 setTimeout(() { console.log(1秒后执行第1个任务); setTimeout(() { console.log(再2秒后执行第2个任务); setTimeout(() { console.log(再3秒后执行第3个任务); setTimeout(() { console.log(再4秒后执行第4个任务); // ... 可以无限嵌套下去 },
; },
; },
; },
;多个异步操作嵌套// 用户注册流程的回调地狱 function registerUser(userData, callback) { validateUser(userData, (isValid) { if (isValid) { checkEmailExists(userData.email, (exists) { if (!exists) { createUser(userData, (userId) { sendWelcomeEmail(userId, (emailSent) { if (emailSent) { logActivity(userId, registered, (logged) { callback(null, { success: true, userId }); }); } else { callback(邮件发送失败); } }); }); } else { callback(邮箱已存在); } }); } else { callback(数据验证失败); } }); }解决办法promise then promise发出了以后then依次执行或者用async await 更简洁好复用 。
// 伪代码示例回调地狱结构 asyncOperation1(data, function(result
{ asyncOperation2(result1, function(result
{ asyncOperation3(result2, function(result
{ // ... 更多嵌套 console.log(最终结果: , result
; }, failureCallback); }, failureCallback); }, failureCallback);这种代码结构可读性差难以维护和调试。
为了解决这个问题JavaScript 社区发展出了更先进的异步处理方案。
回调函数的替代方案随着 JavaScript 语言的发展出现了更优雅地处理异步操作的方式旨在解决回调地狱问题。
其中最主要的是 Promises 和 Async/Await 语法。
Promises 提供了一种链式调用的方式来组织异步操作使得代码结构更扁平化。
4 Async/AwaitAsync/Await 是建立在 Promises 之上的语法糖它允许开发者用更接近同步代码的写法来处理异步逻辑极大地提高了代码的可读性和可维护性。
尽管如此理解回调函数仍然是掌握这些高级概念的基础。
async function声明创建一个绑定到给定名称的新异步函数。
函数体内允许使用await关键字这使得我们可以更简洁地编写基于 promise 的异步代码并且避免了显式地配置 promise 链的需要。
理解异步函数async和await的用法_async await用法-CSDN博客async function - JavaScript | MDN