ES6新标准下JS异步编程Promise解读

简介: ES6新标准下JS异步编程Promise解读

ES5及以下,要实现复杂的异步编程,需要大量运用回调函数,每一个回调函数(JS引擎把它当作一个代码块)依次进入单线程(JS)任务队伍依次执行,而每个回调函数中的执行正确与否无法及时判断,当中信息反馈及显示都只会在最外层函数执行完毕后才反馈给你,让你只能猜测或分析找问题,这将造成大量无法理解的情况出现。对于复杂嵌套回调问题,你将不得不花费大量精力去跟踪各个回调函数运行及清理相互影响。

ES6新标准引入Promise对上述问题进行解决,它的核心思想,是将上一次函数执行返回一个Promise对象,明确指示代码是否成功执行,则你可以基于此成功与否判断,以链式编程方式将复杂嵌套回调函数转换为简单流程化式的形式完成目标任务。

一、Promise的基本用法

每个Promise都会经历一个短暂的生命周期,当处于进行中时标记为pending状态,一旦异步操作结束,Promise标记为settled状态,如果操作出现错误或未完成,标记为unsettle状态。其内部属性[[PromiseState]],分别对应这三种状态,分别是”pending”、“fulfilled”和”rejected”。其内部会自动调用then()方法响应fulfilled成功状态,catch()方法响应rejected。

Then()方法调用时,与异步操作相关的附加数据都会传递给这个完成响应函数。Catch()调用时,所有与失败状态相关的附加数据都会传递给这个拒绝响应函数。

1.基本用法

Promise构造函数可以创建Promise,构造函数接受两个参数,分别是resolve()函数与reject()函数,执行成功完成时调用resolve()函数,失败时则调用reject()函数。

Promise.resolve方法是将一个对象转换成Promise对象,如果入参是一个Promise对象,则直接返回该对象;如果入参是一个thenale对象(表示该对象已经调用了then方法),则返回的是一个新的Promise对象;如果无任何参数,则返回一个fulfilled状态的Promise对象。

Promise.reject方法可以快速返回被rejected的Promise对象。该方法接收一个参数作为入参,这个参数将成来被rejected对象的reason属性,传给rejected回调函数。

   let promise1=new Promise(function(resolve,reject){//模拟函数成功执行

          resolve("成功");

   });

   promise1.then(function(contents){

          console.log(contents);//输出---成功

   });

   let promise2=new Promise(function(resolve,reject){//模拟函数拒绝执行

          reject(new Error("拒绝"));

   });

   promise2.catch(function(err){

          console.log(err);//输出---Error:拒绝

   });

2.具体运用实例

function readNumber(num){//定义Promise实例函数

   return new Promise(function(resolve,reject){

                 if(num<0){

                        reject("输入的数字小于0,拒绝兑换");

                        return;

                 }

                 resolve("输入的数字大于0,执行兑换");

   });

}

let promise1=readNumber(45);//执行成功输入

promise1.then(function(contents){

   console.log(contents);//输出结果:输入的数字大于0,执行兑换

});

promise1.catch(function(err){

   console.log(err);//此函数不会被调用,故无此输出

});

let promise2=readNumber(-6);//执行失败输入

promise2.then(function(contents){

   console.log(contents);//此函数不会被调用,故无此输出

});

promise2.catch(function(err){

   console.log(err);//输入的数字小于0,拒绝兑换

});

二、Promise的串联(链式)用法

Promise每次调用then()方法和catch()方法时,实际上创建了另一个Promise,只有当第一个Promise完成或被拒绝时,第二个才会被解决。因此,就给解决复杂问题链式化提供了条件,而不是用复杂或嵌套式回调函数去解决。其写法如下:

Let p1=new Promise(function(resolve,reject){ });

P1.then(function(){ }).then(funciton(){ })…

以上述实例为具体实现,如下:

function readNumber(num){//定义Promise实例函数

   return new Promise(function(resolve,reject){

                 if(num<0){

                        reject("输入的数字小于0,拒绝兑换");

                        return;

                 }

                 resolve("输入的数字大于0,执行兑换");

   });

}

let promise1=readNumber(45);//执行成功输入

promise1.then(function(contents){

   console.log(contents);//输出结果:输入的数字大于0,执行兑换

}).then(function(){

   console.log("由于有兑换劵,就可以进入购买了");//输出结果:由于有兑换劵,就可以进入购买了

});

let promise2=readNumber(-8);//执行失败输入

promise2.then(function(contents){

   console.log(contents);//输出结果:输入的数字大于0,执行兑换

}).then(function(){

   console.log("由于有兑换劵,就可以进入购买了");//无输出结果:由于readeNumber输入的是-8,第一个then不满足,为拒绝状态,因而第二个then没有调用,而第三个then是基于第二个then呈错误状态的,所有第三个then被执行

}).catch(function(){

   console.log("由于没有有兑换劵,无法进入");//输出结果:由于没有有兑换劵,无法进入

})

三、多Promise响应用法

如果你想通过多个Promise来决定下一步的操作,则可以使用ES6提供的Promise.all()和Promise.race()两个方法来监听多个Promise。

1.Promise.all()方法

Promise.all()方法只接受一个参数并返回一个Promise,该参数是一个含有多个受监视Promise的可迭代对象(例如,一个数组),只有当可迭代对象中所的Promise都被解决后返回的Promise才会被解决,只有当可迭代对象中所有Promise都被完成返回后的Promise才会被完成。

let p1=new Promise(function(resolve,reject){

   resolve(42);

});

let p2=new Promise(function(resolve,reject){

   resolve(43);

});

let p3=new Promise(function(resolve,reject){

   resolve(44);

});

let p4=Promise.all([p1,p2,p3]);

p4.then(function(value){ //因为P4呈完成状态,所以没有调用catch,而是调用的then方法

   console.log(Array.isArray(value));//输出结果:true

   console.log(value[0]);//输出结果:42

   console.log(value[1]);//输出结果:43

   console.log(value[2]);//输出结果:44

})

上述例中,只有当迭代中所有都完成,P4才呈完成状态;反之,只要有一个被拒绝,那么返回的Promise没等其他后面Promise完成就立即呈拒绝状态。如下:

let p1=new Promise(function(resolve,reject){

          resolve(42);

   });

   let p2=new Promise(function(resolve,reject){

          reject(43);

   });

   let p3=new Promise(function(resolve,reject){

          resolve(44);

   });

   let p4=Promise.all([p1,p2,p3]);

   p4.catch(function(value){//因为P4呈拒绝状态,所以没有调用then,而是调用的catch方法

          console.log(Array.isArray(value));//输出结果:false

          console.log(value);//输出结果:43

   });

2.Promise.race()方法

Promise.race()方法也监听多个Promise,与Promise.all方法不一样,它只要有一相Promise被解决则立即返回呈解决状态,无须等到所有的Promise都被解决。

let p1=new Promise(function(resolve,reject){

   resolve(42);

});

let p2=new Promise(function(resolve,reject){

   resolve(43);

});

let p3=new Promise(function(resolve,reject){

   resolve(44);

});

let p4=Promise.race([p1,p2,p3]);

p4.then(function(value){//只要p1呈完成状态,就立即返回呈完成状态,其他后面Promise则被忽略

   console.log(Array.isArray(value));//输出结果:false

   console.log(value);//输出结果:42

});

实际上,传给Promise.race()方法的Promise会进行竞选,以决出哪一个先被解决完成,就选哪一个,并以最先解决状态而呈相同状态,其他的则被忽略。

let p1=new Promise(function(resolve,reject){

   setTimeout(function(){resolve(42);},200);

});

let p2=new Promise(function(resolve,reject){

   resolve(43);

});

let p3=new Promise(function(resolve,reject){

   resolve(44);

});

let p4=Promise.race([p1,p2,p3]);

p4.then(function(value){//由于p1被延迟执行,所以p2最先呈完成状态,故最后输出为p2状态

   console.log(Array.isArray(value));//输出结果:false

   console.log(value);//输出结果:43
相关文章
|
1月前
|
前端开发 JavaScript
用JavaScript 实现一个简单的 Promise 并打印结果
用 JavaScript 实现一个简单的 Promise 并打印结果
|
1月前
|
JSON 前端开发 JavaScript
在 JavaScript 中,如何使用 Promise 处理异步操作?
通过以上方式,可以使用Promise来有效地处理各种异步操作,使异步代码更加清晰、易读和易于维护,避免了回调地狱的问题,提高了代码的质量和可维护性。
|
26天前
|
缓存 JavaScript 前端开发
掌握现代JavaScript异步编程:Promises、Async/Await与性能优化
本文深入探讨了现代JavaScript异步编程的核心概念,包括Promises和Async/Await的使用方法、最佳实践及其在性能优化中的应用,通过实例讲解了如何高效地进行异步操作,提高代码质量和应用性能。
|
21天前
|
JavaScript 前端开发 开发者
探索Node.js中的异步编程之美
在数字世界的海洋中,Node.js如同一艘灵活的帆船,以其独特的异步编程模式引领着后端开发的方向。本文将带你领略异步编程的魅力,通过深入浅出的讲解和生动的代码示例,让你轻松驾驭Node.js的异步世界。
|
1月前
|
JavaScript 前端开发 安全
ECMAScript 6(以下简称 ES6)的出现为 JavaScript 带来了许多新的特性和改进,其中 let 和 const 是两个非常重要的关键字。
ES6 引入了 `let` 和 `const` 关键字,为 JavaScript 的变量管理带来了革新。`let` 提供了块级作用域和暂存死区特性,避免变量污染,增强代码可读性和安全性;`const` 用于声明不可重新赋值的常量,但允许对象和数组的内部修改。两者在循环、函数内部及复杂项目中广泛应用,有助于实现不可变数据结构,提升代码质量。
26 5
|
1月前
|
前端开发 JavaScript Java
一文带你了解和使用js中的Promise
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,正向全栈进发。如果我的文章对你有帮助,请关注我,将持续更新更多优质内容!🎉🎉🎉
21 0
一文带你了解和使用js中的Promise
|
1月前
|
JavaScript API 开发者
深入理解Node.js中的事件循环和异步编程
【10月更文挑战第41天】本文将通过浅显易懂的语言,带领读者探索Node.js背后的核心机制之一——事件循环。我们将从一个简单的故事开始,逐步揭示事件循环的奥秘,并通过实际代码示例展示如何在Node.js中利用这一特性进行高效的异步编程。无论你是初学者还是有经验的开发者,这篇文章都能让你对Node.js有更深刻的认识。
|
1月前
|
前端开发 JavaScript UED
探索JavaScript的异步编程模式
【10月更文挑战第40天】在JavaScript的世界里,异步编程是一道不可或缺的风景线。它允许我们在等待慢速操作(如网络请求)完成时继续执行其他任务,极大地提高了程序的性能和用户体验。本文将深入浅出地探讨Promise、async/await等异步编程技术,通过生动的比喻和实际代码示例,带你领略JavaScript异步编程的魅力所在。
25 1
|
1月前
|
前端开发 JavaScript 开发者
除了 async/await 关键字,还有哪些方式可以在 JavaScript 中实现异步编程?
【10月更文挑战第30天】这些异步编程方式在不同的场景和需求下各有优劣,开发者可以根据具体的项目情况选择合适的方式来实现异步编程,以达到高效、可读和易于维护的代码效果。
|
1月前
|
前端开发 JavaScript 开发者
深入理解JavaScript异步编程
【10月更文挑战第29天】 本文将探讨JavaScript中的异步编程,包括回调函数、Promise和async/await的使用。通过实例代码和解释,帮助读者更好地理解和应用这些技术。
31 3
下一篇
DataWorks