主要作用

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. python基础===利用PyCharm进行Python远程调试(转)

    原文链接:利用PyCharm进行Python远程调试 背景描述 有时候Python应用的代码在本地开发环境运行十分正常,但是放到线上以后却出现了莫名其妙的异常,经过再三排查以后还是找不到问题原因,于是 ...

  2. 【LabVIEW技巧】你可以不懂OOP,却不能不懂封装

    前言 大多数写LabVIEW程序的工程师都不是一个纯软的工程师,很多做硬件的.做机械的.甚至学化学的也会学习LabVIEW. 由于主要重心不在软件,所以LabVIEW程序基本上能用行,也就得到入门容易 ...

  3. UML基础

    UML基础系列:类图   类图描述系统中类的静态结构,它不仅定义系统中的类,描述类之间的联系,如关联.依赖.聚合等,还包括类的内部结构(类的属性和操作).类图描述的是静态关系,在系统的整个生命周期中都 ...

  4. python traceback

    1. Python中的异常栈跟踪 之前在做Java的时候,异常对象默认就包含stacktrace相关的信息,通过异常对象的相关方法printStackTrace()和getStackTrace()等方 ...

  5. IE6/IE7下:inline-block不兼容的问题

    IE6/IE7下对display:inline-block的支持性不好.    1.inline元素的display属性设置为inline-block时,所有的浏览器都支持:    2.block元素 ...

  6. django中使用第三方包实现定时任务

    # 转载请留言联系 在做主页静态化的时候,需要定时生成主页HTML,以保持数据的最新. 定时任务可以用第三方包django-crontab来实现. 附上官方文档:https://pypi.org/pr ...

  7. python_迭代器和生成器

    迭代器和生成器 1.迭代器 特点: 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容 不能随机访问集合中的某个值 ,只能从头到尾依次访问 访问到一半时不能往回退 便于循环比 ...

  8. golang-指针,函数,map

    指针 普通类型变量存的就是值,也叫值类型.指针类型存的是地址,即指针的值是一个变量的地址.一个指针只是值所保存的位置,不是所有的值都有地址,但是所有的变量都有.使用指针可以在无需知道变量名字的情况下, ...

  9. jpa缓存导致无法查询到更新后的数据&android出现ANR的一个解决办法

    1. 向服务器更新记录后查询,始终查询不到更新后的信息 只能查到更新之前的,马上推断出是缓存的问题.网上搜索一番,将问题定位为jpa缓存,我们要设置jpa查询时不从缓存中取,直接从数据库中取,这样便能 ...

  10. python语言的模块化

    在实际工程中使用的编程语言,都有(也应该有)自己的模块化方式,这是由于:一个文件不可能写的无限长,把不同性质和功能的代码放入不同的文件,再由文件组成不同的文件夹,这种方式符合人们思考和理解的习惯,不过 ...