主要作用

1.用来传递异步操作的消息

2.三种状态:pending、Resolved、Rejected,而且只能从第一种状态转到后两者状态之一。

3.缺点

(1)一旦新建就会立即执行

(2)如果不设置回调函数,Promise内部抛出的错误不会反应到外部

(3)如果处于Pending状态,不知道目前到底进行到哪一个阶段。

4.基本用法

var promise = new Promise(function(resolve,reject){
//...
if(/*异步操作成功*/){
resolve(value);//这个函数是js引擎提供的,不用自己部署,这个value可以传递给then方法的参数
}else{
reject(error);//这个函数是js引擎提供的,不用自己部署,这个value可以传递给then方法的参数
}else{
}
})

接收一个函数作为参数,而这个函数的两个参数也是两个函数,是由js引擎提供,不用自己部署。后一个函数不一定要提供

resolve函数的作用是将pending转为resolved状态,在异步操作成功的时候调用,reject则是将其转为rejected状态,在异步操作失败的时候调用。

then()方法

1.作用:当Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。定义在原型对象Promise.prototype上的,为Promise实例添加状态改变时的回调函数

2.then方法返回的是一个新的Promise实例,因此可以采用链式写法,即then方法后面还可以调用另一个then方法。

//异步加载图片
function loadImageAsync(url){
return new Promise(function(resolve,reject){
var image = new Image();
image.onload = function(){
resolve(image);
};
image.onerror = function(){
reject(new Error('cound not load image at'+url));
};
image.src = url;
})
}
//ajax操作
var getJSON = function(url){
var promise = new Promise(function(resolve,reject){
var client = new XMLHttpRequest();
client.open("GET",url);
client.onreadystatechange = handler;
client.responseType = "json";
clent.setRequestHeader("Accept","application/json");
client.send(); function handler(){
if(this.readyState !== 4){
return;
}
if(this.status === 200){
resolve(this.response);//当转为resolved状态的时候,调用then方法
//就会把this.response这个值传递给then方法参数中的value。
}else{
reject(new Error(this.statusText));
//当promise的状态转为rejected时,就会把这个错误信息传递给then方法
}
};
});
return promise;
} getJSON("/post.json").then(function(json)){
console.log(json);//这里的json即是上面的this.response
},function(error){
console.log(error);
} getJSON("/post.json").then(function(json){
return json.post; //这里返回的可能还是一个Promise对象
}).then(function(post)){
//上一个then方法的返回值传递给这个then方法的函数的参数
});

Promise.prototype.catch()

1.这个方法是指定发生错误时的回调函数

注意:如果Promise的状态已经是Resolved,再抛出错误也是无效的。

var promise = new Promise(function(resolve,reject){
resolve("ok");//因为这里已经是resolved状态了,下面再抛出错误也无效
throw new Error('test');
}) promise.then(function(value){
console.log(value);
}).catch(function(error){
console.log(error);
})
//ok这里只会打印ok

还有要注意的是:

(1)Promise对象的错误具有“冒泡”性质,一直会向后面传递,直到捕获为止。不过一般来说,不要在then方法中定义Rejected状态的回调函数,最好在外面用catch方法

(2)还有和传统的try...catch块不同,如果没有使用catch方法来指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应。

(3)如果在Promise内部,状态已经是resolved了,再抛出错误,这个错误也就是在Promise函数体外抛出的。原因是此时Promise的函数体已经运行结束。

(4)catch方法返回的还是一个Promise对象,因此后面还可以紧接着调用then方法。

有两种创建Promise对象实例以及调用它的方法

//第一种,直接利用new命令,创建一个Promise实例

var promise = new Promise(function(resolve,reject){
//...
})
promise.then(function(value){
//...
})

//第二种,用一个函数,然后在其中用return返回一个Promise实例,

var someAsyncThing = function(){
return new Promise(function(resolve,reject){
//下面一行会报错
resolve(x+2);
})
}
someAsyncThing().catch(function(error){
console.log('oh no',error);
}).then(function(){
console.log('carry on');
});
//oh no [ReferenceError: x is not defined]
//carry on

创建Promise实例和then方法和catch方法之间的关系

这里只是我的个人理解:

1.当创建了Promise实例的时候,就会在其中调用两个函数:resolve()和reject(),当resolve()函数成功执行的时候,Promise对象的状态就变成了Resolved,此时就调用then方法,同样的,reject()函数成功执行的时候,Promise对象的状态就变成了Rejected此时也可以调用then方法,但是处理错误的时候,一般推荐使用catch方法。

2.当在创建实例的过程中,会调用resolve()方法,如果这个方法的后面还有throw命令或者抛出错误,此时得判断这个错误是由Promise函数体内部还是外部抛出的,如果是内部抛出,有无catch都无所谓,如果是外部错误,没有catch的话,就会报错(Uncaught Error)。

3.还有在创建实例的过程中,resolve方法的参数,如果是值,就会传递给then方法的函数的参数value。如果还是一个Promise对象,就会返回另一个异步操作。

还有几个小的还很实际的方法

1.Promise.all():用于将多个Promise实例包装成一个新的Promise实例。

参数:可以接受一个数组,但是这个数组的所有成员都是Promise对象的实例,如果不是,就会先调用Promise.resolve方法,将参数转为Promise实例。

也不一定是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例

2.Promise.race():同样是将多个Promise实例包装成一个新的Promise实例。

var p = Promise.race([p1,p2,p3]);

上面的代码中,只要p1,p2,p3中有一个实例率先改变,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就会传递给p的回调函数。同样如果不是Promise实例,就会调用resolve方法来转化为实例。

var p = Promise.race([
fetch('/resource-that-may-a-while'),new Promise(function(resolve,reject){
setTimeout(()=>reject(new Error('request timeout')),5000)
})
])
p.then(response => console.log(response));
p.catch(error => console.log(error));
//上面的代码,如果5秒之内fetch方法无法返回结果,变量p的状态就会变成Rejected,从而触发 catch方法指定的回调函数

3.Promise.resolve()

这个方法就是得到一个Promise对象。

参数:可以是值,也可以是具有then方法的对象

(1)如果是值,如字符串,则返回一个新的Promise对象,那么对象的状态变为resolved,而且参数也会同时传递给回调函数。

(2)其实也可以允许调用的时候,不带参数

4.Promise.reject():也会返回一个新的Promise实例,状态为Rejected。而且reason这个参数会被传递给实例的回调函数。

两个有用的附加方法

ES6的Promise API提供的方法不是很多,可以自己部署一些有用的方法,下面部署两个不在ES6中但很有用的方法。

1.done():这个是为了避免Promise对象的回调链,不管以then方法还是catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为Promise内部的错误冒泡到全局)。

所以,我们提供一个done方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。

asyncFunc()
.then(f1)
.catch(r1)
.then(f2)
.done();
Promise.prototype.done = function(onFulfilled,onRejected){
this.then(onFulfilled,onRejected)
.catch(function(reason){
//抛出一个全局错误
setTimeout(() => {throw reason},0);
});
}

由上面可以看出,done方法可以像then方法那样使用,也可以不提供任何参数,但是不管怎么样,done方法都会捕捉到任何可能出现的错误,并向全局抛出。

2.finally()方法:用于指定不管Promise对象最后状态如何都会执行的操作。它和done方法的最大区别在于,它接受一个普通的回调函数作为参数,该函数不管怎么样都必须执行

下面是一个例子:服务器使用Promise处理请求,然后使用finally方法关掉服务器

server.listen(0)
.then(function(){
//run test
})
.finally(server.stop);
Promise.prototype.finally = function(callback){
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),//调用resolve函数之后返回一个Promise对象,然后再调用then方法
reason => P.resolve(callback()).then(()=> {throw reason})
)
}//㐀Promis对象的 状态如何,都会执行回调函数callback

应用

1.加载图片:可以将图片的加载写成一个Promise,一旦加载完成,Promise的状态就发生变化。

const preloadImage = function(path){
return new Promise(function(resolve,reject){
var image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
})
}

2.Generator函数和Promise的结合

使用Generator函数管理流程,遇到异步操作,通常返回一个Promise对象

//getFoo函数,返回一个Promise对象
function getFoo(){
return new Promise(function(resolve,reject){
resolve('foo');
})
} var g = function* (){
try{
var foo = yield getFoo(); //执行run(g)的时候,这里会返回一个Promise对象,getFoo()是异步操作
console.log(foo);
}catch(e){
console.log(e);
}
};
//总结一下,调用Generator函数,就会返回一个遍历器对象,代表Generator函数的内部指针,以后每次调用遍历器对象的next方法,就会返回一个包括value和done属性的对象。value的值是yield语句后面那个表达式的值;done属性是一个布尔值。
//通过run方法来包装异步函数
function run(generator){
var it = generator();
function go(result){
if(result.done) return result.value;//这里的result是getFoo函数的返回值,也就是一个Promise对象
return result.value.then(function(value){
return go(it.next(value));//这里不用go执行,直接执行it.next(value)也可以,为什么这里要用go???
},function(error){
return go(it.throw(error));
})
}
go(it.next());//执行it.next()之后就会返回一个包含value和done属性的对象
}
run(g);

Promise对象的基本用法的更多相关文章

  1. Promise对象的简单用法

    要了解一个东西,首先要从,它是什么.用来做什么以及怎么取用它这三个方面来了解. 首先,promise是什么? 我们来参考一下MDN对它的定义: Promise 对象用于一个异步操作的最终完成(或失败) ...

  2. Promise对象的含义和基本用法

    1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理更强大. 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件 (通常是一 ...

  3. angular学习笔记(二十八-附2)-$http,$resource中的promise对象

    下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource) ...

  4. ES6深入学习记录(二)promise对象相关

    1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件更合理和强大.ES6将其写进了语言标准,统一了用法,原生提供了promise对象. 所谓Promis ...

  5. es6中的promise对象

    Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...

  6. Promise对象

    1.Promise思想:每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程.这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用. ...

  7. Nodejs与ES6系列2:Promise对象

    2.promise对象 js单线程异步执行的特性,因此在代码中充斥着回调函数.随着回调函数的增加,代码的可读性会愈来愈差,因此引入promise对象是不错的一种选择,可以避免层层回调函数.在ECMA6 ...

  8. ES6 - promise对象

    Promise的设计初衷 我们使用ajax请求数据,得到数据后再对数据进行操作,可是有时候,对得到的数据进行操作的过程中,可能又要用到ajax请求,这时,我们的代码就变成了这样: $.ajax({ s ...

  9. JavaScript 初识Promise 对象

    什么是Promise? 其实, Promise就是一个类,而且这个类已经成为ES6的标准,是 ECMAScript 6 规范的重要特性之一.这个类目前在chrome32.Opera19.Firefox ...

随机推荐

  1. 广度优先算法(BFS)与深度优先算法(DFS)

    一.广度优先算法BFS(Breadth First Search) 基本实现思想 (1)顶点v入队列. (2)当队列非空时则继续执行,否则算法结束. (3)出队列取得队头顶点v: (4)查找顶点v的所 ...

  2. 【Python学习笔记】colormap的参数及其对应的色条

  3. 爬虫===登陆CSDN的方法

    本文主要介绍csdn的登陆,可应用在爬虫上~ # -*- coding:utf-8 -*- import json import requestsfrom xlutils.copy import co ...

  4. 相册框架之AssetsLibrary

    看到项目中用到AssetsLibrary这个框架, 所以研究了一下 其实很简单 - (void)getAlbumPhoto { NSString *tipTextWhenNoPhotosAuthori ...

  5. vscode和phpStorm使用xdebug调试设置

    phpStorm http://www.cnblogs.com/cxscode/p/7045944.html http://www.cnblogs.com/cxscode/p/7050781.html ...

  6. Linux 日志系统及分析

    简介 在Centos 7.x / RHEL 7.x 的版本,系统日志是由一个名为 rsyslog的服务管理的,默认的日志守护进程为 rsyslog , rsyslog 是 syslog 的升级版本,默 ...

  7. js上传文件(图片)限制格式及大小为3M

    本文保存为.html文件用浏览器打开即可测试功能   <form id="form1" name="form1" method="post&qu ...

  8. swagger关闭生产访问

    通过profile注解来处理. Swagger的congif类上声明@Profile({"dev", "test"}),发布到生产上使用product的prof ...

  9. poj 2593&&poj2479(最大两子段和)

    Max Sequence Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 16850   Accepted: 7054 Des ...

  10. Flexigrid默认是可以选择多行

    1.Flexigrid默认是可以选择多行,那么如何设置其只能选一行呢?今天看了看Flexigrid的源码,发现有个属性可以控制: $(this).click(function (e) { var ob ...