【真知拙见】回调地狱和Promise
栏目: JavaScript · 发布时间: 5年前
内容简介:异步编程在JavaScript中非常重要,但是过多的异步编程同时也带来了回调嵌套的问题。以上代码就是一个回调函数。一个函数作为参数需要依赖另一个函数执行调用。但是回调函数有一个致命弱点,容易出现回调地狱(Callback hell)
异步编程在JavaScript中非常重要,但是过多的异步编程同时也带来了回调嵌套的问题。
什么是回调函数?
ajax(url, () => {});复制代码
以上代码就是一个回调函数。一个函数作为参数需要依赖另一个函数执行调用。
但是回调函数有一个致命弱点,容易出现回调地狱(Callback hell)
什么是回调地狱?
let form = document.querySelector('form'); form.onsubmit = function (e) { var name = document.querySelector('input').value; $.ajax({ url: "http://demo.com/submit", type:'POST', data: {name: name}, success: function(res) { if (res.code === 2000) { var h1 = document.querySelector('h1').innerHTML; h1.innerHTML = res.data.name; } } }); }复制代码
像这样,函数作为参数一层层的嵌套,使得代码块看起来庞大、不清晰,不能一下子分清结构层级,这就称为“回调地狱”。
回调地狱的根本问题与缺点:
- 嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身
- 嵌套函数一多,就很难处理错误
- 回调函数態使用try...catch...捕获错误,不能直接return
怎么解决回调地狱?
主要原因是因为开发者的编码习惯导致,我们可以通过以下方式来解决:
- 保持简短的代码风格,尽量使用命名函数,避免使用匿名函数
document.querySelector('form').onsubmit = onFormSubmit(); function onFormSubmit(e) { var name = document.querySelector('input').value; $.ajax({ url: "http://demo.com/submit", type:'POST', data: {name: name}, success: onSuccess(res) }); } function onSuccess(res){ if (res.code === 2000) { var h1 = document.querySelector('h1').innerHTML; h1.innerHTML = res.data.name; } }复制代码
- 模块化,拆分每一个独立的功能函数,封装、打包成一个单独的js文件,通过import导入
// formHandler.js module.exports.formSubmit = onFormSubmit; function onFormSubmit(e) { var name = document.querySelector('input').value; $.ajax({ url: "http://demo.com/submit", type:'POST', data: {name: name}, success: onSuccess(res) }); } function onSuccess(res){ if (res.code === 2000) { var h1 = document.querySelector('h1').innerHTML; h1.innerHTML = res.data.name; } } // index.js var formHandler = require('./formHandler'); document.querySelector('form').onsubmit = formHandler.formSubmit;复制代码
- 处理每一个错误,按照标准规范编码
- Promise/Gengenerator/Async Function
除了常见的一种回调函数作为异步处理,还有promises,Generators,async是处理异步处理的方式
Promise的特点是什么?
Promise译为承诺,承诺在以后、未来会有一个确切的回复,并且该承诺拥有三种状态:
- 等待中(pending)
- 完成了(resolved)
- 拒绝了(rejected)
这个承诺一旦状态变更了以后,就不能再更改状态了
当我们在构造Promise的时候,构造函数内部的代码是立即执行的
new Promise((resolve, reject) => { console.log('new Promise') resolve('success') }) console.log('finish'); // new Promise // finish复制代码
Promise有什么缺点?
无法取消Promise,错误需要通过回调函数来捕获
什么是Promise链?Promise构造函数执行和then函数执行有什么区别?
Promise
实现了链式调用,也就是说每次调用 then 之后返回的都是一个 Promise ,并且是一个全新的 Promise ,原因也是因为状态不可变。如果你在 then 中使用了return ,那么 return 的值会被 Promise.reslove()包装
Promise.resovle(1) .then(res => { console.log(res); // 1 return 2; // 包装成了 Promise.reslove(2) }) .then(res => { console.log(res); // 2 }) 复制代码
Promise也解决了地狱回调的问题:
// old ajax(url, () => { // 处理逻辑 ajax(url1, () => { // 处理逻辑 ajax(url2, () => { // 处理逻辑 }) }) }) // new ajax(url) .then(res => { console.log(res); return ajax(url1); }) .then(res => { console.log(res); return ajax(url2); }) .then(res => console.log(res)); 复制代码
async和await
await 的同步只是在 async 函数里同步,但并不会阻塞其他外部代码的执行。而这也是 await 必须放在 async 函数里的原因
async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。
以上所述就是小编给大家介绍的《【真知拙见】回调地狱和Promise》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Java 线程池实践出真知
- 实践出真知:云计算新风向
- Kafka从上手到实践-实践真知:搭建Zookeeper集群
- Kafka从上手到实践-实践真知:搭建单机Kafka
- Kafka从上手到实践-实践真知:Kafka Java Consumer
- Kafka从上手到实践-实践真知:Kafka Java Producer
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Inside Larry's and Sergey's Brain
Richard Brandt / Portfolio / 17 Sep 2009 / USD 24.95
You’ve used their products. You’ve heard about their skyrocketing wealth and “don’t be evil” business motto. But how much do you really know about Google’s founders, Larry Page and Sergey Brin? Inside......一起来看看 《Inside Larry's and Sergey's Brain》 这本书的介绍吧!