Promise

概念

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。

所`Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

特点

  1. 对象的状态不受外界影响。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。

状态

Promise对象代表一个异步操作,有三种状态:

pending(进行中)、resolved(已成功)和rejected(已失败)。

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

缺点

  1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  3. 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

引子

请看以下代码

setTimeout(function(){
	  console.log('开始')
 },Math.random()*1000);
setTimeout(function(){
	  console.log('执行')
 },Math.random()*1000)
setTimeout(function(){
	  console.log('结束')
 },Math.random()*1000);

那如何让以上代码先 开始执行 最后在 结束呢(跟时间没有任何的关系)

如下:

setTimeout(function(){
	  console.log('开始')
	  setTimeout(function(){
			console.log('执行')
			setTimeout(function(){
					console.log('结束')
			},Math.random()*1000);
	   },Math.random()*1000)
},Math.random()*1000)

回调函数中有回调函数在有回调函数其实这种叫做回调地狱promise就是为了解决回调地狱

promise的三种状态

promise可以理解为是一个机器

而机器是有三种状态的

  • 待机(通过new关键词启动Promise对象里面没有添加任何的对象就是待机状态):pending(Promise函数默认的状态)
  • 工作(成功)(通过new关键词启动的Promise对象里面的回调函数,第一个参数启动是成功状态):resolved(Promise回调函数里面的第一个参数执行)
  • 故障(通过new关键词启动的Promise对象里面的回调函数,第二个参数启动是失败(故障)状态):rejected(Promise回调函数里面的第二个参数执行)

以下是错误写法(没有在Promise里面添加回调函数)

let p = new Promise();//通过new 关键词启动Promise对象 报错:表示语法错误

以下是Promise的三种状态的写法

 // 待机状态 
 let p = new Promise(function(){
	    	
 })//现在才是生成promise对象
 
 // 工作状态
 let p = new Promise(function(reslove,reject){
	   reslove();//让reslove函数执行那么这个promise不在是待机状态而是工作状态
 })
 
 // 故障状态
 let p = new Promise(function(reslove,reject){
	   reject();//让reject函数执行那么这个promise就是失败后的promise
 })

通过new关键词启动Promise函数里面的回调函数

  • 什么也没写默认是待机状态(pending)
  • 第一个参数是工作状态(resolved)
  • 第二个参数是故障状态(rejected)

promise的使用方法

let p = new Promise(function(resolve,reject){
		resolve('我成功了');
	 // [[PromiseStatus]]: "resolved"
     // [[PromiseValue]]: "我成功了"
})
  • [[PromiseStatus]]: 表示promise的当前状态
  • [[PromiseValue]]: 表示promise成功状态下传递的值

Promise对象状态码是'resolved'(成功)就会触发then函数的第一个回调函数

let p = new Promise(function(resolve,reject){
		resolve('我成功了');
}).then((date)=>{//resolved状态的promise对象,就会触发then的第一个回调函数
		console.log('函数触发')
		console.log(date)
		//成功状态下传递的信息会作为then函数第一个回调函数的参数
});
  • resolved状态的promise机器 会触发then的第一个回调函数
  • resolved状态的的数据 会作为参数传递到第一个回调函数中

Promise对象状态码是'rejected'(失败)就会触发then函数的第二个回调函数

let p = new Promise(function(resolve,reject){
		reject('我失败了');
}).then((date)=>{
	    console.log(date)
},(date)=>{
		//当你Promise对象状态码是'rejected'(失败)的时候,就会触发then的第一个回调函数
		console.log(date)
		//失败状态下传递的信息会作为then函数第二个回调函数的参数
});
  • rejected状态的promise机器 会触发then的第二个回调函数
  • rejected状态的的数据 会作为参数传递到第二个回调函数中

then函数他返回的也是一个promise对象,只要是promise就就可以定义他的成功状态和失败状态

 let p = new Promise(function(resolve,reject){
       resolve('我成功了');
	   // reject('我失败了');
}).then((date)=>{
		console.log(date)
		// then函数的返回值默认是 return  undefined(成功状态下的promise)
		return '我是promise对象的返回值';//return 数据可以自己定义promise对象的返回值

		// 那么怎么定义失败状态下的promise对象呢
		return new Promise(function(resolve,reject){
		    reject('我失败了');//现在你then回调函中返回的是一个失败状态下的promise
		//所以这个then函数返回结果就是失败状态下的promise
		//(只有这种情况才能时then函数返回的结果是一个失败状态下的promise)
	})
  }
)

then函数返回的结果也是一个promise机器这个机器的状态取决于触发的回调函数的返回值只有回调函数返回一个失败状态的promisethen函数的返回结果才是失败状态的promise否则 返回结果都是成功状态的promise

如果是Promise是失败的就会触发then的第二个回调函数,因为then的返回结果也是一台promise机器,那么当前then是成功状态下的还是失败状态下的promise的呢???

let p = new Promise(function(resolve,reject){
		// resolve('我成功了');
	    reject('我失败了');
}).then((date)=>{ 
		console.log(date)
},(date)=>{
		console.log(date)
});

初始虽然是定义了失败状态下的promise但是失败后的promise是触发then的第二个回调,而then他的返回结果是一台promise机器而这他机器的状态取决于这个机器的状态取决于触发的回调函数的返回值当前的返回值是undefined(可以人为设置)你只要不是返回结果是失败状态下的promise那么都是成功状态下的promise

let p = new Promise(function(resolve,reject){
	// resolve('我成功了');
	reject('我失败了');
}).then((date)=>{//成功后触发then的第一个回调
	console.log(date)
}).catch((date)=>{//失败后触发catch第一个回调
	console.log(date)
})

当你定义一个失败的promise机器的时候,失败后面的promise机器会走到catch函数里面,而成功后的promise机器就会走到then函数里面

thencatch同样的他们的返回结果都是一台promise机器,而thencatch返回的promise的状态决定你的回调函数的返回值

链式操作的用法

所以,从表面上看,Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。所以使用Promise的正确场景是这样的:

        new Promise(function(a,b){
		 	setTimeout(()=>{
		 		console.log('开始');
		 		a('第一台机器');
		 	},Math.random()*1000)
		 }).then(()=>{
		 	return new Promise((a,b)=>{
		 		setTimeout(()=>{
		 		   console.log('执行')
		 		   a('第二台机器');
		 	    },Math.random()*1000)
		 	})
		 }).then(()=>{
		 	setTimeout(()=>{
		 	    console.log('结束')
		 	},Math.random()*1000)
		 })

Promise的方法

Promise.prototype.catch()

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

p1()
  .then(function(data){
    console.log(data)
  })
  .catch(function(err){
  	console.log(err)
  })
//reject不能结束Promise
//>5,走reject 	
//如果不想promise机器报错  必须把错误信息catch
var z = new Promise(function(a,b){
  
   b('我是失败了')
   console.log('启动promise')
}).then((date)=>{
    console.log(date)
}).catch((date)=>{
    console.log(date)
    return new Promise(function(a,b){
       return b('我是自己定义的失败返回值')
   })
})

z.catch(function(b){
  console.log(b)
})

Promise.all()

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

 let p1 = new Promise(function (res,rej) {
        setTimeout(()=>{
            res('p1成功了');
        },1000)
    })

    let p2 = new Promise(function (res,rej) {
        setTimeout(()=>{
            res('p2成功了');
        },500)
    })

    let p3 = new Promise(function (res,rej) {
        setTimeout(()=>{
            res('p3成功了');
        },300)
    })
const p = Promise.all([p1, p2, p3]);

Promise.all([p1,p2,p3...])

  • 如果所有的promise机器状态都是resolved 则all函数的返回结果就是resolved
  • 如果有一个promise机器状态是rejected 则all函数的返回结果就是rejected

Promise.race()

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

 let p1 = new Promise(function (res,rej) {
        setTimeout(()=>{
            res('p1成功了');
        },1000)
    })

    let p2 = new Promise(function (res,rej) {
        setTimeout(()=>{
            res('p2成功了');
        },500)
    })

    let p3 = new Promise(function (res,rej) {
        setTimeout(()=>{
            res('p3成功了');
        },300)
    })
const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Promise.race([p1,p2,p3...]),返回的是最早有状态的promise机器

Promise.resolve()

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

const jsPromise = Promise.resolve('123');

上面代码将123转为一个 Promise 对象。

Promise.resolve等价于下面的写法。

Promise.resolve('123')
// 等价于
new Promise(resolve => resolve('123'))

Promise.resolve(参数) 生成一个resolved状态的机器

Promise.reject()

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

const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, function (s) {
  console.log(s)
});
// 出错了

上面代码生成一个 Promise 对象的实例p,状态为rejected,回调函数会立即执行。

注意,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。

Promise.reject(参数) 生成一个rejected状态的机器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值