好程序员web前端培训分享如何讲清楚Promise?

简介:

  好程序员web前端培训分享如何讲清楚Promise?此文章主要讲解核心思想和基本用法,想要了解更多细节全面的使用方式,请阅读官方API

  这篇文章假定你具备最基本的异步编程知识,例如知道什么是回调,知道什么是链式调用,同时具备最基本的单词量,例如page、user、promise、then、resovle、reject、pay、fix、order等等,如果你对这些单词非常陌生,那么你需要先花点时间补充一下你的英语

  什么是异步操作?

  所谓异步操作,指的是可以跟当前程序同时执行的操作。举例:

  $("#page").scrolltop(0 ,1000); //使用1秒钟时间将页面滚动至顶部

  $("#nav-float").hide (1000); //使用1秒钟时间将悬浮导航栏隐藏

  只要你稍微有点异步编程经验,就应该知道,这两个方法会同时完成。

  它们的编写顺序并不会影响它们的执行顺序

//异步操作的特点就是,不会打断当前程序的执行

//getUsers请求发出后,会立刻向下继续执行第二个请求

ajax("/getUsers",function(data) {

//回掉函数会在请求成功后调用

})

//resumelist请求会立刻开始,无论getUsers是否结束

ajax("/resumelist", function(data) {

})

//至于哪一个ajax先返回结果并执行回调函数,从代码的编写顺序上是无法确定的。

我们可以给异步操作做一个简单的定义

当一个操作开始执行后,主程序无需等待它的完成,可以继续向下执行。此时该操作可以跟主程序同时(并发)执行。这种操作我们就称之为异步操作。 通常当操作完成时,会执行一个我们事先设定好的回调函数来做后续的处理。

我们常见的异步操作例如:

添加定时器 setTimeout/setInterval

执行某个动画 animate

发起网络请求 request

异步会带来什么问题?

比如我们现在有两个动画,需要按顺序来执行,也就是第一个结束,第二个才能开始

这个时候可能有点麻烦,传统的解决方法是通过回调:

animateA(function( ){

  animateB( );  

})

这种方案显然不太好,如果有很多异步操作需要顺序执行,就会产生所谓的“回调地狱”

ajaxA(function( ){

ajaxB(function( ){

    ajaxC(function( ){

        ajaxD(function( ){

            ......   

        });

    });

});

})

这种代码不管是写起来还是读起来都比较烦人。

我们来看下经过Promise改造后的样子(伪代码)

new Promise(ajaxA)

    .then(ajaxB)

    .then(ajaxC)

    .then(ajaxD);  

Promise的使用及原理

要熟练Promise的的使用,你必须要先搞懂它解决问题的原理

贴一段实际的Promise代码,你来感受一下先:

newPromise(resolve=>{

ajax("/pay/post", data=>resolve() );

}).then(resolve=>{

ajax("/order/fix", data=>{

    //处理数据   

})

})

上面的代码使用了ES6的箭头函数,虽然大大简化了代码的写法,

但对于初级程序猿来讲极不友好

读这种代码简直跟读金刚经差不多。

我们把代码还原成ES5的样子

new Promise(function(resolve){

ajax("/pay/post",function(data){

    resolve();

})

}).then(function(){

ajax("/order/fix",function(data){
})

})

接下来,我们就按照费曼技巧来一步步的学习Promise是如何解决问题的

问题1, 作为一个异步函数,尤其像ajax这种网络请求,连我自己都不能确定函数的执行时间,Promise是怎么知道第一个函数什么时候结束的? 然后再开始执行下一个?

Promise并没有那么神奇,它并不能知道我们的函数什么时候结束,

你注意到上面代码中的第3行了吗

在ajax请求结束执行回调的时候,

我们调用了一个resolve()函数,这句代码非常的关键.

这其实就是在通知Promise,当前这个函数结束啦,

你可以开始执行下一个。 这时Promise就会去执行then里面的函数了。

问题2, 所以按照你的意思,如果我不调用这个方法,Promise就不知道这个函数有没有结束,那么then里面的函数就不会执行,也就是说我的第二个请求就永远不会发送了呗?

Bingo!! 恭喜你已经学会了逻辑推理+抢答。

问题3, 可是这个resolve函数是从哪来的? 需要我自己定义吗? 从代码上看它好像是个参数,那又是谁传入函数中的?

你得先弄明白Promise的基本结构

new Promise(函数1).then(函数2);

我们把函数1和函数2都以参数形式传给了一个Promise对象,

所以接下来函数1和2都会由这个Promise对象控制,

简单的说,函数1和函数2都会由Promise对象来执行。

所以在函数1执行时,参数也当然是由Promise对象传递进去的。

new Promise(function(resolve){

//resolve是Promise对象在调用函数时传入的参数

}).then(函数2);

问题4, Promise对象为啥要在执行第1个任务的时候,把这个resolve函数 传进来,有什么目的?

你说呢?

废屁,知道还用问你?

真是猪脑子,刚才不是已经说了吗?

Promise对象没办法知道我们的异步函数啥时候结束。

那我来问你, 如果你去车站接人,

可是你又不知道对方何时下车,你会咋办?

把我电话号码给他,快到了打我电话呗

没错,Promise解决问题也采用了同样的思路。

它传进来的resolve函数, 就好像一个对讲机,

当我们的异步任务要结束时,通过对讲机 来通知Promise对象。

也就是调用resolve方法

new Promise(function(resolve){

ajax("/pay/post",function(data){

    //当请求结束时,通过调用resolve方法,通知Promise对象,该任务已完成

    resolve(); //收到通知后,Promise会立刻开始函数2的执行

})

}).then(函数2);

懂了,所以这个resolve函数,必须在异步任务的最后调用(例如ajax的回调方法),相当于告诉Promise对象,该任务结束,请开始下一个。

完全正确

问题5, 所以Promise也不过如此嘛,它没有带来什么功能上的革命性变化, 因为使用传统的回调嵌套的方式,同样可以完成效果。 说白了它就是编码方式上的改进??

基本是这样的,但Promise带来的编码方式以及异步编程思路上的进步是非常巨大的。

问题6, 那如果我有ajaxA、ajaxB、ajaxC三个异步任务,想按照先A后B再C的顺序执行,像这样写行吗?

new Promise(function(resolve){

ajax("/AAA", function(){

    resolve(); //通知Promise该任务结束

})    

}).then(function(resolve){

ajax("/BBB", function(){

    resolve();//通知Promise该任务结束

})

}).then(function(){

ajax("/CCC", function(){ //.... })

})

上面的这种写法是不对的。

Promise的中文含义是“承诺”,

则意味着,每一个Pormise对象,代表一次承诺

而每一次承诺,只能保证一个任务的顺序,也就是说

new Promise(A).then(B); 这句话表示, 只能保证A和B的顺序

一旦A执行完,B开始后,这次承诺也就兑现了,Promise对象也就失效了

那如果还有C呢? 我们就必须在函数B中,

重新创建新的Promise对象,来完成下一个承诺,具体的写法就像这样:

new Promise(函数1(resolve){

ajaxA("xxxx", function(){

    resolve();//通知Promise该任务结束

})    

}).then(函数2(){

//在函数2开始运行后,第一次创建的Promise对象完成使命,已经不能再继续工作。

//此时,我们创建并返回了新的Promise对象

return new Promise(function(resolve){

    ajaxB("xxxx", function(){

        resolve();//通知新的Promise对象该任务结束

    })    

})

}).then(函数3(){ //尽管这里使用了链式调用,但负责执行函数3的,已经是新的Promise对象了

// 如果,我们还有ajaxD需要顺序调用

// 那就必须在这里重新new Promise()对象了

ajaxC("xxx", function(){     })

})

问题7, 懂了,那Promise还有什么其它强大的功能吗?

有啊,例如: 如果我有 A,B,C 三个异步任务,ABC同时开始执行

当A,B,C三个任务全部都结束时,执任务D,

传统方法实现起来就比较复杂,Promise就非常简单,就像这样:

Promise.all([new Promise(A), new Promise(B), new Promise(C)])

.then(function(){

D();

});

问题8, 那如果我希望A,B,C 其中任意一个任务完成,

就马上开始任务D,该怎么做?

Promise.race([new Promise(A), new Promise(B), new Promise(C)])

.then(function(){

D();

});

相关文章
|
1月前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
50 3
|
23天前
|
前端开发 JavaScript
探索现代Web应用的微前端架构
【10月更文挑战第40天】在数字时代的浪潮中,Web应用的发展日益复杂多变。微前端架构作为一种新兴的设计理念,正逐步改变着传统的单一前端开发模式。本文将深入探讨微前端的核心概念、实现原理及其在实际项目中的应用,同时通过一个简单的代码示例,揭示如何将一个庞大的前端工程拆分成小而美的模块,进而提升项目的可维护性、可扩展性和开发效率。
|
14天前
|
前端开发 JavaScript 搜索推荐
HTML与CSS在Web组件化中的核心作用及前端技术趋势
本文探讨了HTML与CSS在Web组件化中的核心作用及前端技术趋势。从结构定义、语义化到样式封装与布局控制,两者不仅提升了代码复用率和可维护性,还通过响应式设计、动态样式等技术增强了用户体验。面对兼容性、代码复杂度等挑战,文章提出了相应的解决策略,强调了持续创新的重要性,旨在构建高效、灵活的Web应用。
27 6
|
22天前
|
消息中间件 前端开发 JavaScript
探索微前端架构:构建现代Web应用的新策略
本文探讨了微前端架构的概念、优势及实施策略,旨在解决传统单体应用难以快速迭代和团队协作的问题。微前端允许不同团队独立开发、部署应用的各部分,提升灵活性与可维护性。文中还讨论了技术栈灵活性、独立部署、团队自治等优势,并提出了定义清晰接口、使用Web组件、状态管理和样式隔离等实施策略。
|
1月前
|
监控 前端开发 JavaScript
探索微前端架构:构建可扩展的现代Web应用
【10月更文挑战第29天】本文探讨了微前端架构的核心概念、优势及实施策略,通过将大型前端应用拆分为多个独立的微应用,提高开发效率、增强可维护性,并支持灵活的技术选型。实际案例包括Spotify和Zalando的成功应用。
|
1月前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
34 3
|
1月前
|
前端开发 JavaScript API
前端框架新探索:Svelte在构建高性能Web应用中的优势
【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
46 2
|
1月前
|
监控 前端开发 JavaScript
前端技术探索:构建高效、可维护的Web应用
【10月更文挑战第23天】前端技术探索:构建高效、可维护的Web应用
48 0
|
2月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
160 2
|
2月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
45 0