Promise、async、await

转载于https://blog.csdn.net/qq_34645412/article/details/81170576

https://segmentfault.com/a/1190000007535316

1.Promise


Promise是为了解决地狱回调的问题。
如果我们有多个ajax请求,第二个ajax请求的参数需要从第一个ajax请求的结果中得到,第三个ajax请求的参数需要从第二个ajax请求的结果中得到,那么总要等到第一个请求的结果之后才能请求第二个,等到第二个请求结果才能请求第三个,嵌套层级过深容易陷入地域回调,每次读取文件后还要进行逻辑的判断或者异常的处理,整个回调函数会非常复杂而且难以维护。
Promise是异步编程的一种解决方案,表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。Promise 对象就是为了解决这个问题而提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。它其实是一个构造函数。他本身是同步执行的,then是异步执行。构造函数是通过new来调用的。

function Person(){
}
var person = new Person();//调用构造函数

Person();//普通函数调用

我们new一个Promise的时候,就已经执行了。所以我们用Promise的时候一般是包在一个函数里面,在需要的时候去运行这个函数。
但是如果用.then就直接调用了。

Promise对象有以下两个特点:

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中),
    fullfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,“承诺”,表示其他手段无法改变。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fullfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。这时就称为resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

Promise对象自己身上有resolve、reject、all这几个方法,原型上有then、catch等方法。

resolve是Promise成功时候的回调,它把promise的状态修改为fullfilled。
reject是Promise失败时候的回调,它把状态修改为rejected。
这些我们都能在then中捕捉到。
then方法可以接收两个参数,第一个对应resolve的回调,第二个对应reject的回调(一个成功的回调函数,一个失败的回调函数)
catch是和then方法并行的方法,是用来捕获异常的,和then中第二个参数接收的reject的回调一样的。(前者和后者的区别是,如果在执行resolve的回调报错了的时候,并不会报错卡死js,而是会进入catch方法中输出报错原因。当没有写reject回调的时候失败时会进入.catch,两个都写了的时候就近调用,两个都写了且resolve报错的时候进入catch)。
all也是和then方法并行的方法,提供并行执行异步操作能力,它在所有异步操作执行完且执行结果都是成功的时候才执行回调。

Promise
		.all([promiseClick3(), promiseClick2(), promiseClick1()])
		.then(function(results){
			console.log(results);
		});

all接收一个数组参数,参数为所有需要执行的异步操作方法,里面的值最终都返回Promise对象。等它们都执行完后才会进入到then里面。then输出一个数组,数组中保存着多个异步方法的成功回调结果(但是这个保存的顺序是由执行完是由all后面的顺序决定的,无论他们谁先运行完。如果有一个失败就不执行then回调了)
这样以后就可以用all并行执行多个异步操作,并且在一个回调中处理所有的返回数据,比如你需要提前准备好所有数据才渲染页面的时候就可以使用all,执行多个异步操作将所有的数据处理好,再去渲染。
race也是和then并行的方法。all是等所有的异步操作都执行完了再执行then方法,那么race方法就是相反的,谁先执行完就先执行回调。先执行完的不管是进行了rece的成功回调还是失败回调,其余的都将不会再进入race的任何回调。

Promise
		.race([promiseClick3(), promiseClick2(), promiseClick1()])
		.then(function(results){
			console.log('成功',results);
		},function(reason){
			console.log('失败',reason);
		});

2.async


async是异步的意思,这个关键字放在一个函数前面,用来声明一个函数是异步的。

async function person(){
    
}

async函数总是返回一个Promise,并且Promise对象的状态值是resolve(成功的)。如果你没有在async函数中没有写return,那么Promise对象resolved值就是undefined。如果写了return,那么return的值就会作为你成功的时候传入的值。例如代码中有return <非promise>语句, JavaScript会自动把返回的这个value值通过promise.resolved()包装成Promise对象。
Promise.resolve(x)可以看作是new Promise(resolve=>resolve(x))的简写,可以用于快速封装字面量对象或其他对象,将其封装成Promise实例。

async function person(){
    return 'aa';
}

person().then((data)=>{
    console.log(data) //aa
})

我们也可以显示的返回一个promise

async function person(){
	return Promise.resolve('aa')
}

Promise的特点———无等待。所以在没有await的情况下执行async函数,它会立即执行,返回一个Promise对象,并且,绝不会阻塞后面的语句。这和普通返回Promise对象的函数并无二致。

3.await


await是等待的意思, 等待一个表达式
语法: 【返回值】= await 表达式。表达式是一个Promise对象或者任何要等待的值。
await只能在async函数内部使用
返回值:返回Promise对象的处理结果。如果等待的不是Promise对象,则返回该值本身。

  1. 等待的是一个promise对象:
    await表达式会暂停当前async函数的执行,等待Promise处理完成。若Promise正常处理(fullfilled),其回调的resolve函数参数作为await表达的值,继续执行 async函数。
    如果Promise处理异常,await表达式会把Promise的异常原因抛出。用try、catch去捕获。


    这就是 await 必须用在 async 函数中的原因。async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行。

    赋值的时候堵塞,会先执行await等待的promise中的同步代码(promise本身是同步的),然后再执行async函数外层的同步代码,再等到promise的成功或是失败回调,去把表达式赋值;再接着执行完async函数。
    如果等待的promise没有resolve或者reject,await表达式没有得到值,会一直堵塞这个async函数,本函数的后面代码不会执行。
  2. 等待的不是一个promise对象:
    await也会堵塞后面的代码,执行完await后面的表达式,然后先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的值作为await表达式的结果,并接着执行完async函数
    就算等待的普通函数没有返回值,也会执行普通函数,只不过await表达式的值是undefined。
try{
	let a = await promise;
}catch(err){
	console.log(err)
}

Promise 通过 then 链来解决多层回调的问题,现在又用 async/await 来进一步优化它

promise当执行到resolve或者reject的时候,把.then放到微任务队列中。
await 后面的全部代码放到.then()中去,所以await后面的全部代码要放到微任务队列。
Promise.resolve().then(()=>{})不放入微任务队列

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值