Promise对象的基础入门学习

开发 前端
Promise对象是CommonJS工作组提出的规范。Promise原本只是社区提出的构想,一些外部函数库率先实现了该功能,ES6中将其写入了语言标准。Promise是啥,它就是一个javascript中一个对象,起着代理作用,充当异步操作与回调函数之间的中介。

[[171668]]

今天来学习下Promise吧!其实这在笔试上也是一个考点。

基本介绍

Promise对象是CommonJS(熟悉的名字吧- -)工作组提出的规范.Promise原本只是社区提出的构想,一些外部函数库率先实现了该功能,ES6中将其写入了语言标准.

目的:为异步操作提供统一接口

Promise是啥,它就是一个javascript中一个对象,起着代理作用,充当异步操作与回调函数之间的中介。

避免类似于

 

这种嵌套地狱的产生.让我们的代码变得更加简单易读使用了Promise,大家都说好

  1. (new Promise(f1).then(f2)); 

总结:Promise使得异步操作的向下发展变成横向发展,程序流程变得清晰,易于阅读。

基本思想

  • 异步任务返回一个Promise对象,它有三种状态

1.pending(未完成)

2.resolved,fulfilled(已完成)

3.rejected(失败)

  • 它有两种变化途径

1.pending --> resolved/fulfilled

2.pending --> rejected

  • 它有两种结果

1.异步操作成功,返回一个值,状态变为resolved

2.异步操作失败,抛出一个错误,状态变为rejected

Promise使用.then()方法添加回调函数,then接收两个回调函数,***个为成功时的回调函数,另一个为失败时的回调函数.主要为状态改变时调用相对的回调函数.

而且then可以链式调用。

基本使用

Promise构造函数接受一个函数作为参数,而该函数两个参数分别是resolve和reject.它们由JS引擎提供,不需要自己部署.

  1. Promise(function(resolve,reject){}) 

resolve函数作用为:将Promise对象从未完成变为成功(Pending->Resolved),异步操作成功时调用,并将异步操作的结果作为参数传递出去.

reject函数作用为:将Promise对象从未完成变为失败(Pending->Rejected),异步操作失败时调用,并将异步操作报出的错误作为参数传递出去.

Promise.then()方法可以用于指定Resolved状态和Reject状态的回调函数.

  1. promise.then(function(value){//成功+_+!},function(value){//失败Q_Q}); 

我们只想对异常进行处理时可以采用promise.then(undefined, onRejected)这种方式,或者promise.catch(onRejected)

!注意!此处有坑,接下来在深入节会进行讲解

Promise.all()方法接收一个promise对象的数组为参数,当这个数组中所有的Promise对象全部变成resolve/reject状态的时候,才会调用.then方法,其中传入的promise是同时开始,并行执行的。

  1. promise.all([promise1,promise2,.....]); 

Promise.race()方法和Promise.all()方法一样接收一个promise对象的数组作为参数,但是数组中有一个promise对象进入fulfilled或rejected状态,就会开始后续处理. 

  1. promise.race([promise1,promise2,.....]); 

相关的语法糖 

  1. Promise.resolve(42); 
  2. //等价于 
  3. new Promise(function(resolve){ 
  4.     resolve(42); 
  5. }); 
  6.  
  7. Promise.reject(new Error("出错了")); 
  8. //等价于 
  9. new Promise(function(resolve,reject){ 
  10.     reject(new Error("出错了")); 
  11. });  

深入

关于Thenable对象

这是非常类似于Promise的东西,拥有.then方法.

其中比较经典的例子就是jQuery.ajax()返回的值就是thenable的. 

  1. var promise = Promise.resolve($.ajax('/json/comment.json')); 

这样就可以将thenable对象转化为promise对象

传送门:Promise.resolve()

关于promise设计:总是异步操作

看代码就能明白这个地方的问题了. 

  1. var promise = new Promise(function (resolve){ 
  2.     console.log("inner promise"); // 1 
  3.     resolve(42); 
  4. }); 
  5. promise.then(function(value){ 
  6.     console.log(value); // 3 
  7. }); 
  8. console.log("outer promise"); // 2 
  9. //结果是 
  10. /* 
  11. inner promise // 1 
  12. outer promise // 2 
  13. 42            // 3 
  14. */  

可以看出,即使我们调用promise.then时promise对象已经确定状态,Promise也会以异步的方式调用回调函数,这就是Promise设计上的规定方针.

关于调用then/catch

每次调用then/catch,都会返回一个promise对象,这一点上我们通过使用===就可以判断出来每次promise对象其实都是不一样的

then和catch的错误处理区别

这点和上一点联合起来很容易理解

直接上图吧,来自于JavaScript Promise迷你书(中文版)

 在结合我们的代码吧 

  1. // <1> onRejected不会被调用 
  2. function badMain(onRejected) { 
  3.     return Promise.resolve(42).then(throwError, onRejected); 
  4. // <2> 有异常发生时onRejected会被调用 
  5. function goodMain(onRejected) { 
  6.     return Promise.resolve(42).then(throwError).catch(onRejected); 
  7.  

onFullfilled中发生的错误,如在<1>里面throwError中的错误,是不会导致onRejected的执行(捕获异常)的,我们只能通过后面的catch方法才能捕获.

基本应用

不兼容方面

  1. 不兼容就是用polyfill吧
  2. 关于IE8以及以下版本中,catch会由于在ES3中为保留字,导致identifier not found错误,对此我们可以通过["catch"]或者then(undefined,function(){})来进行catch,而某些类库中,采用了caught作为函数名来规避该问题.值得注意的是,有很多压缩工具中自带了.catch转["catch"]

应用示例:

加载图片 

  1. var preloadImage = function(path){ 
  2.   return new Promise(function(resolve,reject){ 
  3.     var image = new Image(); 
  4.     image.onload = resolve; 
  5.     image.onerror = reject; 
  6.     image.src = path; 
  7.   }) 
  8. preloadImage("https://dn-anything-about-doc.qbox.me/teacher/QianDuan.png").then(function(){ 
  9.   alert("图片加载成功"); 
  10. },function(){ 
  11.   alert("图片加载失败"); 
  12. })  

Ajax操作 

  1. function search(term) { 
  2.     var url = 'http://example.com/search?q=' + term; 
  3.     var xhr = new XMLHttpRequest(); 
  4.     var result; 
  5.     var p = new Promise(function(resolve, reject) { 
  6.         xhr.open('GET', url, true); 
  7.         xhr.onload = function(e) { 
  8.             if (this.status === 200) { 
  9.                 result = JSON.parse(this.responseText); 
  10.                 resolve(result); 
  11.             } 
  12.         }; 
  13.         xhr.onerror = function(e) { 
  14.             reject(e); 
  15.         }; 
  16.         xhr.send(); 
  17.     }); 
  18.     return p; 
  19. search("Hello World").then(console.log, console.error);  

回到最初吧,其实Promise对象优点还是在于规范的链式调用,可以清晰看出程序流程.并且对于错误还能定义统一的处理方法。

责任编辑:庞桂玉 来源: segmentfault
相关推荐

2021-04-22 22:26:13

Java语言IT

2010-06-18 09:57:46

C#UML基础

2018-07-11 13:33:43

大数据人工智能Hadoop

2021-01-28 08:34:30

Java对象定义

2021-01-18 08:52:28

Java对象多态

2009-07-03 14:31:43

学习JSP

2020-12-24 08:36:14

JavaJava基础

2011-09-27 13:52:41

2024-07-09 09:33:18

2017-09-04 22:41:31

深度学习矩阵运算代码

2017-09-18 10:48:06

深度学习零基础入门

2012-02-29 00:00:43

Linux鸟哥

2020-07-29 17:35:08

Promise源码前端

2011-02-24 11:10:33

Konqueror

2011-07-06 14:12:14

Objective-C

2023-09-15 15:31:23

异步编程Promise

2009-06-17 09:58:48

JBoss Rules

2022-02-22 19:04:01

Perl编程语言

2020-11-16 16:13:06

网络安全互联网渗透测试

2015-07-23 11:59:27

JavascriptPromise
点赞
收藏

51CTO技术栈公众号