ES6之Promise对象知识点总结(七)

news/2024/7/11 0:06:34 标签: ES6, Promise

还是要强调一下,我的ES6学习主要参考的是阮一峰大神的书,作笔记的目的,就是把对于我来说比较重要或者易错的点整理出来方便自己再次学习有所偏重,真的对这些不懂的请看原文:http://es6.ruanyifeng.com/#docs/promise阮一峰大神写得真的很好哎

先简单介绍一下Promise对象

  1. 用于异步计算
  2. 可以将异步操作队列化,按照期望的顺序执行,返回预期的结果
  3. 可以在对象之间传递和操作Promise,帮助我们处理队列

Promise对象的特点:

  • promise对象一旦建立就会立即执行
  • 对象的状态不受外界影响,promise代表一个异步操作,有三种状态:pending(进心中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
  • promise状态一旦改变,就不会再变,任何时候都可以得到这个结果。

promise的长处和缺点 

长处:

  • promise可以将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数。
  • promise提供统一的接口,使得控制异步操作更容易
缺点:
  • promise一旦建立就会立即执行,无法中途取消。
  • 如果不设置回调函数,promise内部抛出的错误,不会反应到外部。
  • promise在pending状态时,无法知道当前进展到哪一个阶段。

Promise对象的用法

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不用自己部署

resolve函数的作用是,将Promise对象的状态从pending变为resolved,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用,将Promise对象的状态从pending变为rejected,在异步操作失败的时候调用。并将异步操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

.then()方法接收两个回调函数作为参数,第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中第二个函数是可选的,不一定要提供。这两个函数都接收Promise对象传出的值作为参数

Promise状态发生改变,会触发.then()里面的响应函数,.then()根据其最终状态,选择特定的状态响应函数执行,状态响应函数,可以返回新的Promise或其它值,如果返回新的Promise,那么下一级.then()会在新的Promise状态改变之后执行,如果返回其它任何值,则会立刻执行下一级.then()。没有明确返回值,就相当于return undefined,仍然不会影响Promise执行,即使在里面return false也不会影响下一步,false可以直接传到下一步。

嗯、看下面的例子吧

  console.log('here we go');
    new Promise(resolve =>{
        setTimeout(()=>{
            resolve('hello');
    },2000);
    })
    .then(value=>{
        console.log(value);
        return new Promise(
            resolve=>{
                setTimeout(
        ()=>{
            resolve('leo')
    },2000);
        });
    }).then(value=>{
        console.log(value+' world');
    })
分析一下:首先控制台立刻打印出here we go 然后有一个Promise实例,状态成功后,2秒后调用resolve()函数,并把hello传递给了.then()方法,所以打印的是hello,然后,then()方法中返回一个新的Promise实例,所以下一级的函数要等到这个新的Promise执行完之后才能执行,这个新的promise实例状态改变后再次调用resolve函数,然后把'leo'传递到下一级.then()方法中,所以最后打印的是leo world

再看个例子

   console.log("donna");
    let promise = new Promise(resolve=>{
        setTimeout(()=>{
            console.log("hello leo");
            resolve('jon is good');
 },1000);
    });
    setTimeout(()=>{
        promise.then(value=>{
            console.log(value);
    });
    },3000);

嗯,原理和上一个差不多,只不过,这个例子中.then()没有直接链接在Promise实例后面,这种写法也是可以的。这个结果是,先打印donna,然后hello leo  最后打印jon is good 

再看一个容易掉坑的例子

   console.log('here we go');
   new Promise(resolve=>{
       setTimeout(()=>{
           resolve('hello');
 },2000);
   }).then(value=>{
       console.log(value+ ' world');
 (function (){
     return new Promise(resolve=>{
         setTimeout(()=>{
             console.log("donna");
             resolve("bangbang");
     },4000)
     });
 }());
return false;
 }).then(value=>{
     setTimeout(()=>{
     console.log(value+ " bingbing");
 },3000)

 })

先猜猜结果,看你会不会掉坑

嗯,宣布结果 打印的先后顺序为 here we go  、hello world  、false  bingbign、donna

跟你想象的一样吗?提醒一下,第一个then方法里面返回的Promise实例是在立即执行函数里面的,不是这个then方法的返回值,它的返回值是false,所以它不会等里面的定时器执行完,就跳到了下一个then方法中执行(记得value是上一个then方法返回的false),执行完之后,才去执行上面的定时器中的内容


Promise.prototype.catch方法是.then(null,rejection)的别名。用于指定错误时的回调函数

如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误,另外,then方法指定的回调函数,如果抛出错误,也会被catch方法捕获。

p.then((val) => console.log('fulfilled:', val))
  .catch((err) => console.log('rejected', err));

// 等同于
p.then((val) => console.log('fulfilled:', val))
  .then(null, (err) => console.log("rejected:", err));

嗯,再看一个例子

const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error('test');
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});

// 写法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error('test'));
});
promise.catch(function(error) {
  console.log(error);
});
const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test

这三种方法是等价的,从上面我们也可以发现,reject方法的作用等同于抛出错误

注意:如果,promise的状态已经成功,再抛出错误是无用的,因为Promise的状态一旦确定就无法改变

一般来说,不要在then方法里面定义reject状态的回调函数(即then的第二个参数),总是使用catch方法。跟传统的try/catch代码块不同的是,如果没有使用catch方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应。

所以总是建议,Promise对象后面要跟catch方法,这样可以处理Promise内部发生的错误。catch方法返回的还是一个Promise对象,因此后面还可以接着调用then方法。Promise对象的错误具有“冒泡”性质,会一直向后传递,直到捕获为止。也就是说,错误总是会被下一个catch语句捕获,如果没有报错则会跳过catch方法,接着运行后面的then方法指定的回调函数。

Promise.resolve()方法:有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用

Promise.resolve等价于new Promise(resolve=>resolve('foo'));

Promise.resolve方法的参数分四种情况。

  • 参数是一个Promise实例:这种情况Promise.resolve将不做任何修改,原封不动地返回这个实例。
  • 参数是一个thenable对象:thenable对象指的是具有then方法的对象。Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法。
//使用Promise.resolve方法
 let thenable = {
     then:function(resolve){
         resolve("donna");
     }
 }
  Promise.resolve(thenable).then(value=>{
     console.log(value);//donna
 });
 //上面的方法类似下面的这样
 new Promise(resolve=>{
     resolve("donna");
 }).then(value=>{
     console.log(value);
 })

  • 参数不是具有then方法的对象,或根本不是对象

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为resolved

 let obj= {
     str:function(){
         console.log(123);
     }
 }
  Promise.resolve(obj).then(value=>{
     console.log(value);//{str:f}
 });

上面的代码生成一个新的Promise对象的实例,由于对象obj不是thenable对象,返回Promise实例的状态从一一生成就是resolved,所以回调函数会立即执行,Promise.resolve方法的参数会同时传给回调函数

  • 不带有任何参数

Promise.resolve方法允许调用时不带参数,直接返回一个resolved状态的Promise对象。所以如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法

注意:立即resolve的Promise对象,实在本轮“事件循环”的结束时,而不是在下一轮“事件循环”的开始时

 setTimeout(()=>{
     console.log("weiwei");
 },0);
 let thenable = {
     str:function(){
         console.log(123);
     }
 }
  Promise.resolve(thenable).then(value=>{
     console.log(value);//{str:f}
 });
console.log("hongbao");//hongbao  {str:f}  weiwei

上面的代码中,setTimerout(fn,0),在下一轮“事件循环”开始时执行,Promise.resoolve()在本轮“事件循环”结束时执行,console.log('hongbao')则是立即执行,因此最先输出。

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected

注意:Promise.reject()方法的参数会原封不动传给后续方法的参数,这一点与Promise.resolve方法不一致

const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

上面代码,Promise.reject方法的参数是一个thenable对象,执行以后,后面的catch方法的参数不是reject抛出的“出错了”这个字符串,而是thenable

Promise.all():该方法用于将多个Promise实例,包装成一个新的Promise实例

Promise.all对象接收一个数组作为参数,并且数组的成员都是Promise实例,如果不是,就会先调用上面谈到的Promise.resolve方法将参数转为Promise实例,再进一步处理。(注意:Promise.all的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例)返回值是一个新的Promise实例,传递给该对象的回调函数

当所有的Promise都完成,该Promise完成,返回值是全部值的数组,有任何一个失败,该Promise失败,返回值是第一个失败的子Promise的结果,也会传递给该对象的回调函数。

Promise.race()方法类似Promise.all()方法,区别在于它有任意一个完成就算成功














http://www.niftyadmin.cn/n/952081.html

相关文章

原生js打造自定义播放器

用到的技术,主要是video的相关知识:实现的功能是去掉自带的控制条,按自己想要的形式设置视频的控制条:有播放与暂停(play()方法和pause()方法)、拖拽控制条控制视频的播放进度,并且控制条随着视…

Remoting服务集成到IIS的简单总结

因为项目的Remoting服务有可能集成到IIS中,所以下午利用一些时间,做了一个例子,实现了需要的功能,代码就凑合一下。现在把这个过程总结一下:1. 创建远程对象类Class1,它实现一个接口Interface1public class Class1 : Marsha…

python求表达式的值_python 求值表达式解析

采用中缀转后缀的算法。注意我输入的格式。#注意格式def suffix(st):listopt[" "]listnum[" "]for i in range(0,len(st)):if(differ(st[i])1): #判断,对运算符操作if(len(listopt)):if(dictopt[st[i]] > dictopt[listopt[len(listopt)-1]])…

ES6之Generator(1)知识点总结(八)

学ES6的时候,我一般会先看一些讲ES6的视频,对要学的概念有个大致的理解之后,再来看阮老师的文章,嗯、每次都会有,原来如此的感觉,阮老师讲的真的很详细,也很好理解,整理一遍是希望能…

DataTable的细节

DataTable是表格数据块在内存中的表示。虽然可以手动以编程形式构建一个DataTable,但通常使用DataSet和定义在System.Data.OleDb或System.Data.SqlClient命名空间中的类型,以动态获得一个DataTable。表A-7描述了DataTable中的一些核心属性。 表A-7 Data…

python 单向链表查找倒数第n个元素_求单链表倒数第N个数

昨天我们解决了单链表逆序的问题,同时给出了三种解决方案。今天我们解决另外一个常见面试题:求单链表倒数第N个数。这个问题很有代表性。不管是顺数n个还是倒数n个,其实都是距离-标尺问题。标尺是一段距离可以用线段的两个端点来衡量&#xf…

ES6之Generator(2)知识点总结(九)

记笔记,主要是为了提高学习效率,避免只看不动手,领略不到书的精髓,忽略到书中的重点知识,本文学习主要是根据阮一峰大神走的,很感谢阮一峰大神的无私奉献。如果想要了解更详细的关于本节的内容可以看阮一峰…

python dialogflow_构建一个简单的 Google Dialogflow 聊天机器人 [下]

这部分内容主要包括实体的抽取和定义,意图识别和简单的多轮对话。使用实体提取数据此页面描述了如何从用户的查询中提取参数值(实体数据)。添加参数到您的意图参数是用户查询中提取的重要且相关的单词或短语,因此您的聊天机器人可以提供适当的响应。 您将…