Promise 的介绍和基本使用

目录

1、Promise 是个啥?

2、为啥用 Promise ?

3、Promise 的基本使用

4、Promise 的三种状态

5、Promise 的链式调用

6、Promise.all 方法的使用

7、Promise.race 方法的使用


1、Promise 是个啥?

Promise 是 ES6 中一个非常重要和好用的特性,它是前端异步编程的一种解决方案。常见的 Promise 使用场景就是发送网络请求的时候,比如 JavaScript 代码执行到中间要发送一个网络请求,如果同步发送网络请求则 JavaScript 代码在网络请求结果返回之前会进入等待状态,不会继续往下执行,这样就造成了堵塞,针对这一问题就需要用到异步发送网络请求,一边发送网络请求,一边往下继续执行 JavaScript 代码,当请求的数据返回的时候,再执行其对应的回调函数就可以了。

补充:Promise 并不是前端发明的,而是借鉴后端的。1976 年,Daniel P.Friedman 和 David Wise 二人提出 Promise 思想
,后人基于此发明了 Future、Delay、Deferred 等,前端结合 Promise 和 JS,制订了 Promise/A+ 规范,该规范详细描述了Promise的原理和使用方法。这有一篇解析 详解Promise/Promise/A+ 规范

如果你想学习并使用 Promise,在知道原理的基础上,最好能熟记下面这句话:return new Promise((resolve,reject)=>{});

2、为啥用 Promise ?

这里举一个夸张的例子方便理解,就是大名鼎鼎的回调地狱:

假如我们需要通过一个 url1 从服务器加载一个数据 data1data1 中包含了下一次请求的 url2

然后我们需要通过 data1 取出 url2 ,从服务器加载数据 data2data2 中包含了下一次请求的 url3 ,

然后我们需要通过 data2 取出 url3,从服务器加载数据 data3data3 中包含了下一次请求的 url4 

然后再发送网络请求 url4 ,获取最终的数据 data4 。上面这个例子对应的 jQuery-Ajax 代码如下:

$.ajax('url1',function(data1){    //通过data1获取url2
    $.ajax('url2',function(data2){    //通过data2获取url3
        $.ajax('url3',function(data3){    //通过data3获取url4
            $.ajax('url4',function(data4){    //通过data3获取url4
                console.log(data4);    //最终获取的数据data4
            })
        })
    })
})

上面这段代码正常情况下是可以正常运行并获取我们想要的结果,但是这样的代码格式难看而且不容易维护(代码中注释的地方可能有多行代码),Promise 就能针对这一问题,实现一种更加优雅的方式来进行异步操作。

3、Promise 的基本使用

这里拿一个 setTimeout 方法模拟异步操作,Promise 方法中需要传入一个函数,在执行该函数时会传入两个参数:resolvereject,这两个参数也是函数类型。Promise 方法中的函数的函数体存放需要发送的异步请求,最终的处理代码放到.then .catch 方法中。异步操作执行成功的话会调用 resolve 函数,一旦调用 resolve 函数就会调用 .then 函数,异步操作执行失败的话会调用 reject 函数,一旦调用 reject 函数就会调用 .catch 函数,这样就将异步请求和需要执行的操作进行分离,使代码更加清晰,也方便后期的维护。

new Promise((resolve,reject) => {
	setTimeout(() => {
		//成功的时候调用resolve
		resolve('you are so bangbang')
		
		//失败的时候调用reject
		reject('what is your problem,laodi')
	},1000)
}).then((data) => {
	console.log(data);
}).catch((err) => {
	console.log(err);
})

4、Promise 的三种状态

在开发中如果有异步操作,就可以给异步操作包装一个 Promise ,异步操作之后会有三种状态,分别是:

pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。

fulfill:完成状态,当我们主动回调了 resolve 时,就处于该状态,并且会回调 .then() 方法

reject:拒绝状态,当我们主动回调了 reject 时,就处于该状态,并且会回调 .catch() 方法

一个 Promise 的状态只能从等待状态转换到完成状态或者拒绝状态,不能逆向转换,同时完成状态和拒绝状态不能相互转换。Promise 必须实现 then 方法,而且 then 返回的是一个 Promise对象 ,同一个 Promise 的 then 可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致,then 方法可以接受两个参数,第一个参数是成功时的回调,在 Promise 由等待状态转换到完成状态时调用,另一个是失败时的回调,在 Promise 由等待状态转换到拒绝状态时调用。同时,then 可以接受另一个 Promise 传入。上面这种说法的代码如下(.then方法和.catch方法合并):

new Promise((resolve, reject)=>{
	setTimeout(function(){
		//成功的时候调用resolve
		resolve('you are so bangbang')
		//失败的时候调用reject
		reject('what is your problem,laodi')
	},1000)
}). then(data=>{
	console. log(data);
}, error=>{
	console. log(error);
}

对于 Promise 的状态,记住两点:

(1)一个 promise 的当前状态只能是 pending、fulfilled 和 rejected 三种之一。状态改变只能是 penaing 到 fufilled 或者 pending 到 rejected 。状态改变不可逆。

(2)promise 的 then 方法接收两个可选参数,表示该 promise 状态改变时的回调(promise.then(onFulfilled,onRejected))。then 方法返回一个 promise,then 方法可以被同一个 promise 调用多次。

5、Promise 的链式调用

Promise.then() 返回的是一个新的 Promise实例。因此可以采用链式写法,即 then() 方法后面再调用另一个 then() 方法。比如要发送两次网络请求,第一次请求结束后,在 then() 方法体中 return 一个新的 Promise 对象,执行第二次网络请求,那就可以在第一个 then() 方法后面直接写一个 then()方法,当两次请求都结束的时候再执行后面这个 then() 方法。

new Promise((resolve,reject) => {
	//第一次网络请求的代码
	setTimeout(() => {
		//成功的时候调用resolve
		resolve('helloWorld111')
	},1000)
}).then((data) => {
	//第一次拿到结果的处理代码
	console.log(data);
	
	return new Promise((resolve,reject) => {
		//第二次网络请求的代码
		setTimeout(() => {
			//成功的时候调用resolve
			resolve('helloWorld222')
		},1000)
	})
}).then((data) => {
	//第二次拿到结果的处理代码
	console.log(data);
})

6、Promise.all 方法的使用

假如开发工程中有的需求依赖两个或多个请求,没有拿到所有的请求结果则不能往下执行相关的操作,这个时候就可以用到Promise.all() 方法了,该方法需要传入的是几个请求的数组,最终结果也是以一个数组的方式返回,可以通过数组下标具体拿到每个请求的结果。

Promise.all([
    new Promise((resolve,reject) => {
        //请求一:()
        $ajax({
            url:'url1',
            success:function(data){
                resolve(data)
            }
        })
    }),
    new Promise((resolve,reject) => {
        //请求二:
        $ajax({
            url:'url2',
            success:function(data){
                resolve(data)
            }
        })
    }),
]).then(results => {
    result[0]
    result[1]
})

7、Promise.race 方法的使用

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "one"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "two"); 
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value); // "two"
  // 两个都完成,但 p2 更快
});

现在主流的框架是 axios,它就是配合 Promise 使用,了解完 Promise 后不妨看一下 axios 框架的介绍和基本使用 

你可能感兴趣的:(网络请求相关)