Promise基础篇

什么是Promise

MDN定义:Promise对象用于异步操作,他表示一个尚未完成且预计在未来完成的异步操作。
Promise是异步编程的解决方案,相较传统的解决方案更加合理和强大。

回调函数

request('value1', '', function(data1) {
    console.log('第一次请求成功', data1);
    request('value2', data1, function (data2) {
        console.log('第二次请求成功', data2);
        request('value3', data2, function (data3) {
            console.log('第三次请求成功', data3);
            //request... 继续请求
        }, function(error3) {
            console.log('第三次请求失败', error3);
        });
    }, function(error2) {
        console.log('第二次请求失败', error2);
    });
}, function(error1) {
    console.log('第一次请求失败', error1);
});

上述例子出现了多层嵌套,这就是常说的回调地狱,而使用Promise,可以利用then进行链式回调,将异步操作以同步操作的流程表示出来。

sendRequest('value1', '').then(function(data1) {
    console.log('第一次请求成功', data1);
    return sendRequest('value2', data1);
}).then(function(data2) {
    console.log('第二次请求成功', data2);
    return sendRequest('value3', data2);
}).then(function(data3) {
    console.log('第三次请求成功', data3);
}).catch(function(error) {
    //catch捕捉前面的错误
    console.log('sorry, 请求失败了', error);
});

Promise有三种状态

  • pending:初始值
  • fulfilled:操作成功
  • rejected:操作失败

Promise的缺点:

  • Promise一旦新建就会执行,无法中途取消
  • 若不设置回调函数,Promise内部抛出错误,不会反映到外部
  • 处于pending状态时,无法得知目前是刚开始还是即将完成

Promise的基本用法

const promise = new Promise((resolve,reject)=>{
	if(/*异步操作成功*/){
		resolve(res);
	}else{
		/*异步操作失败*/
		reject(error);
	}
})

我们构建一个PromisePromise接受一个函数作为参数,该函数的两个参数分别是resolvereject。它们是两个函数,由JavaScript引擎提供。
resolve 异步操作成功时调用,并将操作结果以参数传递出去。
reject 异步操作失败时调用,并将操作的报错以参数传递出去。

Promise实例生成后,使用then方法指定resolved状态和reject状态的回调函数

promise.then((value)=>{
	//success
},(error)=>{
	//failure
});

then方法可以接受两个回调函数作为参数,第一个函数是promise对象的状态改变为resolved是调用,第二个函数是promise对象状态改变为rejected时调用。第二个函数为可选。

Promise新建后会立即执行。then方法中指定的回调函数,将在当前脚本所有同步任务执行完成后才会执行

const promise = new Promise((resolve,reject)=>{
	console.log('success);
	resolve();
})
promise.then(() => {
	console.log('resolved');
})
console.log('promsie')

// success
// promise
// resolved

promise对象实现ajax操作:

const request = (param) => {
	return new Promise ((resolve,reject) => {
		var xhr = new XMLHttpRequest();
		xhr.open("get", param.url, true);
		xhr.send(param.data);
		xhr.responseType = "json";
		xhr.onreadystatechange = () =>{
			if(xhr.readyState=== 4) {
				if(xhr.status === 200){
					try{
						resolve(xhr.responseText + 'success');
					}catch(err){
						reject(err)
					}
				}else{
					//failure
					reject(new Error(xhr.statusText));
				}
			}
		}
	})
}

request(param).then((res) => {
	console.log(res);
},(error) => {
	console.error(error);
})

上述例子,request是对XMLHttpRequest对象的封装,用于发出一个http请求,并返回一个Promise对象。

Promise.prototype.then()

then 方法为Prommise实例添加状态改变时的回调函数,即resolved和rejected。
then方法返回一个新的Promise对象,因此可以采用链式写法。

Promise.prototype.catch()

catch方法用于指定发生错误时的回调函数。

request(param).then((res) => {
	console.log(res);
}).catch((error) => {
	console.error(error);
})

//=========== 等同于 ===============

request(param).then((res) => {
	console.log(res);
}).then(undefined||null,(error) => {
	console.error(error);
})

Promise抛出一个错误,就被catch的回调函数捕获

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

上面代码的写法等同于

const promise = new Promise((resolve,reject) => {
	try{
		throw new Error('error')
	}catch{
		reject(error);
	}
});

从以上代码可以看出,reject方法等同于抛出错误。
Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。

const promise = new Promise((resolve,reject) => {
	resolve(a + 2) //此处报错 a未定义
});
promise.then(() => {
	console.log('promise');
})
setTimeout(() => {
	console.log('promise test')
},5000)

// a is not defind
// promise test

上面代码中,promise对象的内部语法有错,浏览器会打印错误提示,但不会终止脚本执行,5秒后会输出promise test,即promsie内部的错误不会影响到外部的代码。

Promise.resolve()

Promise.resolve能将现有的对象转为Promise对象,它可以看做是new Promise()的快捷方式。

Promise.resolve(value)

//=============等同于===================
new Promise(resolve => {
	resolve(value);
})

Promise.reject()

该方法和Promise.resolve()类似,也会返回一个Promise对象,该对象会进入rejected状态,

Promise.all()

Promise.all()用于将多个Promise实例,包装成一个新的Promise实例,该方法接受一个数组作为参数,数组的每一项都为一个Promise,若不是,会调用Promise.resolve()方法,将参数转换为Promise实例。它的状态由参数中的Promise实例决定。

  • 当数组中的Promise实例都为fulfilled,它的状态才会变为fulfilled,并将Promise的返回结果按参数的顺序,存入数组。
var p1 = new Promise(resolve => {
	setTimeout(resolve,2000,"frist")
})
var p2 = new Promise(resolve => {
	resolve('second')
})
var p3 = new Promise(resolve => {
	setTimeout(resolve,500,"third")
})
Promise.all([p1,p2,p3]).then(value => {
	console.log(value);
})

//
//["first","second","third"]
  • 当数组中的Promise实例其中之一的状态变为rejected,它的状态也会变为rejected,并把第一个被reject的Promise的返回值传给回调函数。
var p1 = new Promise(resolve => {
	setTimeout(resolve,1000,"first")
})
var p2 = new Promise((resolve,reject) => {
	setTimeout(reject,500,"second")
})
var p3 = new Promise((resolve,reject) => {
	setTimeout(reject,500,"third")
})
Promise.all([p1,p2,p3]).then(value => {
	console.log('resolve',value);
},error => {
	console.log('reject',error);
})

//
// reject second

Promise.race()

该方法同样用于将多个Promie实例包装成一个新的Promise实例,它与Promise.all()方法一样,会将不是Promise实例的参数转换为Promise实例。与Promise.all()不同于,当数组中有一个实例改变了状态,它的状态就会改变,并把率先改变的Promise实例的返回值,传递给回调函数。

var p1 = new Promise((resolve,reject)=>{
    setTimeout(reject, 2000,'one');
})
var p2 = new Promise((resolve,reject)=>{
    setTimeout(resolve, 1000,'two');
})

Promise.race([p1,p2]).then(value=>{
    console.log('resolve',value)
},error=>{
    console.log('reject',error)
})

//
// resolve two
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值