【JS】以下几行代码中,Promise对比回调的优势在哪里?
最近学ES6
,了解到promise
,可以通过then().then().then()
的方式解决回调地狱
想请问:
像下边的简单逻辑情况下,两者的功效可能一样的。
那么promise
还有什么优势吗?
如果有,在哪里,希望得到老司机码力加持,请不惜金码,敲上两行。
谢谢你的帮助
function afterSomeSeconds( callBackFn ){setTimeout(()=>{
callBackFn('2秒过去了,异步执行结束');
}, 2 * 1000);
};
afterSomeSeconds(function toLog(msg){
console.log(msg)
});
console.log('主线程1');
// ▲传统回调,
// ——————————————————————————————————————————————————————————
// ▼ES6的Promise
function afterSomeSecondsPromise(){
return new Promise(function(resolve, reject){
setTimeout(()=>{
resolve('3秒过去了,异步执行结束');
}, 3 * 1000);
})
}
afterSomeSecondsPromise().then(msg=>{
console.log(msg)
});
console.log('主线程2');
控制台打印如下:主线程1
主线程2
2秒过去了,异步执行结束
3秒过去了,异步执行结束
回答
从本质来讲两者都能实现我们想要的功能,但真正投入开发,你会发现promise跟async/await搭配简直就是一把梭子。
利用promise跟async/await可以将异步操作改成‘伪同步’(实质还是异步),编码上思路更加顺溜了。
往往项目开发我们都会封装通用的请求函数
使用回调的封装就是
export const Http= { get:function(url,data,sucCb,errCb){
axios.get(url,{params:data})
.then(function(res){
if (res.data.code==200) {
//这里可以写一些请求操作成功需要统一处理的代码,例如弹框显示成功
sucCb(res.data.data)
}else {
//这里可以写一些请求操作失败需要统一处理的代码,例如弹框显示失败
errCb(res.data.message);
}
})
.catch(function(err){
//这里可以写一些请求操作失败需要统一处理的代码,例如弹框显示失败
errCb(err);
})
},
post:function(...){...},
put:function(...){...},
delete:function(...){...},
}
如何调用呢
Http.get(url,data,function(res){ //请求成功啦,做处理
},function(err){
//请求失败啦,快做处理
})
当接口很多的时候,这种反复的操作能写到你烦。
那我们使用promise封装呢?结果会是怎么样
export const Http= { get:function(url,data){
return new Promise((resolve,reject)=>{
axios.get(url,{params:data})
.then(function(res){
if (res.data.code==200) {
//这里可以写一些请求操作成功需要统一处理的代码,例如弹框显示成功
resolve(res.data.data)
}else {
//这里可以写一些请求操作失败需要统一处理的代码,例如弹框显示失败
errCb(res.data.message);
}
})
.catch(function(err){
//这里可以写一些请求操作失败需要统一处理的代码,例如弹框显示失败
reject(err);
})
})
},
post:function(...){...},
put:function(...){...},
delete:function(...){...},
}
如何调用呢
async getData(){ let mydata = await Http.get(url,data);
}
一看码量减少了一半不止,而且封装了通用请求函数,可以对api做统一管理,放在一个api.js里。例如
export const Orders = { get:function(){ return Http.get("deliver/oil-orders"); },
deliver:function(){ return Http.get("deliver/oil-orders",{section:'delivering'}); },
put:function(data){ return Http.put(`deliver/oil-orders/${data.id}`,data); }
}
export const User = {
code:function(phone){ return Http.get("sms/code",{phone:phone}); },
login:function(data){ return Http.post("deliver/login",data); },
get:function(){ return Http.get("deliver/user/info",null); }
}
以后每次调用接口都是简单的‘伪同步’
let user = await User.get();
let orders = await Orders.get();
是不是更加简洁了?
有啊!
1. await 加持下更爽
在支持 await 的环境下可以直接
var msg = await afterSomeSecondsPromise();console.log(msg);
2.和其他异步操作结合,或者自身重复调用
fetch('./api') .then(afterSomeSecondsPromise)
.then(msg => fetch('./api', {method: 'POST', body: msg}))
.catch(err => console.error(err)); // .catch 可以捕获甚至 afterSomeSecondsPromise 里的异常
afterSomeSecondsPromise()
.then(afterSomeSecondsPromise)
.then(afterSomeSecondsPromise);
// 试试回调版本?
我补充一点 错误处理也会变优雅, 用习惯后用 throw
来做流程控制会变为常态.
区别就是 Promise
更简洁可读性好 易操作 功能更强大一点 更加主流
你这个就好像在对比 jquery
和 vue,react
,es5
和es6
不是说他差 只是有更好的 当然用更好的
优势最主要的就是体现在可读性上而已,你这里的例子过于简单了,所以说明不了问题,我给你从网上找了个图:
这个图虽然有些夸张,但足够说明问题,就是当嵌套的层级多了,可读性变差、变量命名冲突等问题就会被放大,而且这只考虑了串行调用的情况,如果并行呢,请自动脑补。
再有一个问题就是,callback 的函数签名没有约束,意味着如果你愿意的话,想怎么传参就怎么传,虽然在 nodejs 有其约定俗成的签名,比如 err 是第一个参数,之后是 data 等等,但如果是在个人项目中的话,是否遵守这个规范显然取决于开发者本身了。
使用 Promise 的好处就是一定程度上解决了回调地狱带来的问题,注意这里是一定程度上噢,而不是完全解决,由于 Promise 本身的实现有规范,因此各种实现库除去定制化的功能以外,基本一定程度上保证了一致性,比如 .then 或者 .catch,这些 api 各种库都是一样的。
当然了,还有其他的异步解决方案,不过大同小异,基本上都是在可读性、可维护性、一致性上取舍,你见的多了、用的多了就知道了。
setTimeout会把你延迟执行的内容扔到下一个EventLoop里.
Promise会将你要执行的内容扔到当前EventLoop的最后.
上面回答的太多了,就是从使用上看起来更加清晰,ES7的async和await到后续使用会更加频繁
你描述都提到了用promise解决回调地狱,但你提供的代码只是一个简单的异步处理,根本就没形成地狱。你尝试写一个3秒后打印3然后过了2秒打印2然后再过过4秒打印4,然后看一下有什么区别。
你再思考一下,假如你的异步任务发生错误你该怎么处理?当然你用计时器是没有发生错误的可能的,你改用ajax,或是nodejs的io操作。
你的问题是不了解promise的使用场景,实际上promise就是为了让异步操作变得更优雅而存在的。
ES7的async和await到后续使用会更加频繁
关于回调、Promise、async/await 的博客我好像写了不少了
- 从小小题目逐步走进 JavaScript 异步调用
- 从地狱到天堂,Node 回调向 async/await 转变
- 理解 JavaScript 的 async/await
- 闲谈异步调用“扁平”化
- ES6 的 for..of 和 Generator,从伪数组 jQuery 对象说起
- 通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise
你是用了setTimeout
这种定时器再回调,那么在传统的单线程执行过程中,如果你需要去异步的处理一些事情而不影响主线程呢!建议多了解一下异步到底是怎么回事,而不是用定时器来描述。
以上是 【JS】以下几行代码中,Promise对比回调的优势在哪里? 的全部内容, 来源链接: utcz.com/a/87214.html