对Promise状态的理解和基本用法
2018-01-12 15:31
851 查看
Promise状态的理解
用new Promise实例化的Promise对象有三个状态:“has-resolution” - Fulfilled
reslove(成功时),调用onFulfilled
"has-rejection" - Rejected
reject(失败时)。调用Rejected
"unresolve" - Pending
既不是resolve也不是reject状态,也就是Promise刚刚被创建后的初始化状态。
note:
1、在Chrome中输出resolve可以得到Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined},可以看出[[PromiseStatus]]中存储的就是Promise的状态,但是并没有公开访问[[PromiseStatus]]的用户API,所以暂时还无法查询其内部状态。2、Promise中的then的回调只会被调用一次,因为Promise的状态只会从Pending变为Fulfilled或者Rejected,不可逆。
then与catch返回新的Promise
在Promise中无论是then还是catch方法,都会返回返回一个新的Promise对象。var aPromise = new Promise(function (resolve) { resolve(100); }); var thenPromise = aPromise.then(function (value) { console.log(value); }); var catchPromise = thenPromise.catch(function (error) { console.error(error); }); console.log(aPromise !== thenPromise); // => true console.log(thenPromise !== catchPromise);// => true
所以像下面这样将链式调用分开写是不成功的
// 1: 对同一个promise对象同时调用
then方法
var aPromise = new Promise(function (resolve) { resolve(100); }); aPromise.then(function (value) { return value * 2; }); aPromise.then(function (value) { return value * 2; }); aPromise.then(function (value) { console.log("1: " + value); // => 100 });
由于每次调用then方法都会返回一个新的Promise,所以导致最终输出100而不是100 2 2。
Promise.all()的使用
有时候需要多个彼此没有关联的多个异步任务全部执行完成后再执行后面的操作,这时候就需要用到Promise.all(),它接收一个Promise的对象的数组作为参数,当这个数组里的所有Promise对象全部变成resolve或者reject的时候,它才会去调用后面的.then()。这里需要说明一点,两个彼此无关的异步操作会同时执行,每个Promise的结果(即每个返回的Promise的resolve或reject时传递的参数)和传递给Promise.all的Promise数组的顺序一致。也就是说,假设有两个异步操作TaskA和TaskB,如果传入顺序为Promise.all([TaskA,TaskB]),则执行完成后传给.then的顺序为[TaskA,TaskB]。
function setTime(time){ return new Promise((resolve)=>{ setTimeout(()=>resolve(time),time); }) }let startTime = Date.now();
Promise.all([setTime(1),setTime(100),setTime(200)]) .then((value)=>{ console.log(value); //[1,100,200] console.log(Date.now() - startTime); //203 });
从上面函数的输出值可以看出Promise.all()里的异步操作是同时执行的而且传给.then()的顺序和Promise.all()里的顺序一样。最终执行时间约为200ms,为什么不是200ms,这里涉及到关于setTimeout的精准问题,不在这里讨论。
Promise.race()的使用
Promise.rance()的用法与Promise.all()类似,不同的地方在于Promise.all()是在接收到的所有Promise都变为FulFilled或者Rejected状态之后才会继续进行后面的处理,而Promise.rance()只要有一个Promise对象进入FullFilled或者Rejected状态,就会继续进行后续处理。这相当于Promise.all()进行且运算而Promise.rance()进行或运算。但是这里有一点需要注意一下:var taskA = new Promise(function (resolve) { setTimeout(function () { console.log('this is taskA'); resolve('this is taskA'); }, 4); }); var taskB = new Promise(function (resolve) { setTimeout(function () { console.log('this is taskB'); resolve('this is taskB'); }, 1000); }); Promise.race([winnerPromise, loserPromise]).then(function (value) { console.log(value); }); /* 输出结果: this is taskA this is taskA this is taskB */
从这里可以看出,在第一个Promise变为FulFiled状态运行then里的回调后,后面的Promise并没有停止运行,而是接续执行。也就是说, Promise.race 在第一个promise对象变为Fulfilled之后,并不会取消其他promise对象的执行。
Promise.resolve()的使用
在Promise的链式调用中,有可能各个task之间存在相互依赖,例如TaskA想给TaskB传递一个参数,像下面这样:/*例1.使用Promise.resolve()启动*/ let task1 = (value1)=>value1+1; let task2 = (value2)=>value2+2; let task3 = (value3)=>{console.log(value3+3)}; Promise.resolve(1).then(task1).then(task2).then(task3);//console => 7 /*例2.普通的返回一个Promise*/ function task1(value1){ return new Promise((resolve,reject)=>{ if(resolve){ resolve(value1+1); }else{ throw new Error("throw Error @ task1"); } }); } function task2(value2){ return new Promise((resolve,reject)=>{ if(resolve){ resolve(value2+2); }else{ throw new Error("throw Error @ task1"); } }); } function task3(value3){ return new Promise((resolve,reject)=>{ if(resolve){ console.log(value3+3); }else{ throw new Error("throw Error @ task1"); } }); } task1(1).then(task2).then(task3);//console => 7
关于reslove与reject有以下两点说明:
reslove函数的作用是将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
reject函数的作用是将Promise对象状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时候调用,并将异步操作报出的错误作为参数传递出去;
所以从上面的例子和它们的用法可以看出,如果想要传递给后面task有两种方法:
如果使用Promise.resolve()启动Promise,则像例1中那样在需要传递的参数前面加return即可。
如果是利用Promise包装了任务,则把想要传递给下一个task的参数传入resolve()即可。
特别说明:如果需要resolve()往后传递多个参数,不能直接写resolve(a1,a2,a3),这样只能拿到第一个要传的参数,需要以数组或对象去传递
let obj = {a1:a1,a2:a2,a3:a3}; resolve(obj) //or let arr =[a1,a2,a3]; resolve(arr);
Promise的reject和异步操作error的理解
function ReadEveryFiles(file){ return new Promise((resolve,reject)=>{ if(resolve){ fs.readFile(`${__dirname}/jQuery/${file}`,(err,data)=>{ if(err){ console.log(err); }else{ let obj = {data:data,file:file}; resolve(obj); } }); }else{ //promise reject error } }); }
这里的readFile的error和Promise的reject不一样,一个是readFile过程中导致的错误,而另一个是Promise做处理的时候导致的错误,可以这样理解,假设读取文件成功了,但是Promise还需要讲这个异步操作得到的数据拿到处理,在Promise做这些操作的时候可能出错。
相关文章推荐
- ES6基础之详解Promise基本用法
- Promise对象的含义和基本用法
- std:move基本用法和理解
- 读写锁的基本理解及简单用法
- promise的基本用法
- 5 -- Hibernate的基本用法 --5 深入理解持久化对象
- Promise对象的含义和基本用法
- monkeyrunner其他测试例子收集,便于理解python一些基本用法
- Promise对象的基本用法
- Promise对象的含义和基本用法
- ES6 学习之promise 基本用法
- Promise对象的含义和基本用法
- Promise的基本用法简介和特点
- Android AsyncTask 基本用法,参数和步骤理解,开启异步任务之旅
- Promise对象的含义和基本用法
- 初识React及属性和状态的基本用法
- 加深理解进程基本状态转化
- JavaScript中promise的基本用法
- Android Swich的基本用法,保存状态等
- Android OpenGL ES零基础系列(一):理解GLSurfaceView,GLSurfaceView.Render的基本用法