异步解决方案----Promi与Await

更新时间:2023-07-21 11:09:39 阅读: 评论:0

异步解决⽅案----Promi与Await
宣布英语
前⾔
异步编程模式在前端开发过程中,显得越来越重要。从最开始的XHR到封装后的Ajax都在试图解决异步编程过程中的问题。随着ES6新标准的到来,处理异步数据流⼜有了新的⽅案。我们都知道,在传统的ajax请求中,当异步请求之间的数据存在依赖关系的时候,就可能产⽣很难看的多层回调,俗称'回调地狱'(callback hell),这却让⼈望⽽⽣畏,Promi的出现让我们告别回调函数,写出更优雅的异步代码。在实践过程中,却发现Promi并不完美,Async/Await是近年来JavaScript添加的最⾰命性的的特性之⼀,Async/Await提供了⼀种使得异步代码看起来像同步代码的替代⽅法。接下来我们介绍这两种处理异步编程的⽅案。
⼀、Promi的原理与基本语法
1.Promi的原理
Promi 是⼀种对异步操作的封装,可以通过独⽴的接⼝添加在异步操作执⾏成功、失败时执⾏的⽅法。主流的规范是 Promis/A+。Promi中有⼏个状态:
pending: 初始状态, ⾮ fulfilled 或 rejected;
文明美德伴我成长fulfilled: 成功的操作,为表述⽅便,fulfilled 使⽤ resolved 代替;
rejected: 失败的操作。
pending可以转化为fulfilled或rejected并且只能转化⼀次,也就是说如果pending转化到fulfilled状态,那么就不能再转化到rejected。并且fulfilled和rejected状态只能由pending转化⽽来,两者之间不能互相转换。
2.Promi的基本语法
Promi实例必须实现then这个⽅法
then()必须可以接收两个函数作为参数
then()返回的必须是⼀个Promi实例
<script src="/bluebird/3.5.1/bluebird.min.js"></script>//如果低版本浏览器不⽀持Promi,通过cdn这种⽅式
<script type="text/javascript">
function loadImg(src) {
var promi = new Promi(function (resolve, reject) {
var img = ateElement('img')
resolve(img)
}
平假名翻译reject('图⽚加载失败')
}
img.src = src
})
return promi
}
var src = '/static/img/index/logo_new.png'
var result = loadImg(src)
result.then(function (img) {
juventusconsole.log(1, img.width)
return img
}, function () {
2016高考分数查询console.log('error 1')
}).then(function (img) {
console.log(2, img.height)
})
</script>
⼆、Promi多个串联操作
Promi还可以做更多的事情,⽐如,有若⼲个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执⾏错误处理函数。要串⾏执⾏这样的异步任务,不⽤Promi需要写⼀层⼀层的嵌套代码。
有了Promi,我们只需要简单地写job1.then(job2).then(job3).catch(handleError);
其中job1、job2和job3都是Promi对象。
⽐如我们想实现第⼀个图⽚加载完成后,再加载第⼆个图⽚,如果其中有⼀个执⾏失败,就执⾏错误函数:
var src1 = '/static/img/index/logo_new.png'
var result1 = loadImg(src1) //result1是Promi对象
var src2 = '/545862fe00017c2602200220-100-100.jpg'
var result2 = loadImg(src2) //result2是Promi对象
result1.then(function (img1) {
console.log('第⼀个图⽚加载完成', img1.width)
return result2  // 链式操作
}).then(function (img2) {
console.log('第⼆个图⽚加载完成', img2.width)
}).catch(function (ex) {
console.log(ex)
})
这⾥需注意的是:then ⽅法可以被同⼀个 promi 调⽤多次,then ⽅法必须返回⼀个 promi 对象。上例中result1.then如果没有明⽂返回Promi实例,就默认为本⾝Promi实例即result1,result1.then返回了result2实例,后⾯再执⾏.then实际上执⾏的是
result2.then
三、Promi常⽤⽅法
除了串⾏执⾏若⼲异步任务外,Promi还可以并⾏执⾏异步任务。
加班英语
备受青睐的意思试想⼀个页⾯聊天系统,我们需要从两个不同的URL分别获得⽤户的个⼈信息和好友列表,这两个任务是可以并⾏执⾏的,⽤Promi.all()实现如下:
var p1 = new Promi(function (resolve, reject) {
tTimeout(resolve, 500, 'P1');
});
var p2 = new Promi(function (resolve, reject) {
territorial
tTimeout(resolve, 600, 'P2');
});
// 同时执⾏p1和p2,并在它们都完成后执⾏then:
Promi.all([p1, p2]).then(function (results) {
console.log(results); // 获得⼀个Array: ['P1', 'P2']
});
有些时候,多个异步任务是为了容错。⽐如,同时向两个URL读取⽤户的个⼈信息,只需要获得先返回的结果即可。这种情况下,⽤Promi.race()实现:
var p1 = new Promi(function (resolve, reject) {
tTimeout(resolve, 500, 'P1');
});
var p2 = new Promi(function (resolve, reject) {
tTimeout(resolve, 600, 'P2');
});
Promi.race([p1, p2]).then(function (result) {
console.log(result); // 'P1'
});
由于p1执⾏较快,Promi的then()将获得结果'P1'。p2仍在继续执⾏,但执⾏结果将被丢弃。
总结:Promi.all接受⼀个promi对象的数组,待全部完成之后,统⼀执⾏success;
Promi.race接受⼀个包含多个promi对象的数组,只要有⼀个完成,就执⾏success
接下来我们对上⾯的例⼦做下修改,加深对这两者的理解:
var src1 = '/static/img/index/logo_new.png'
var result1 = loadImg(src1)
var src2 = '/545862fe00017c2602200220-100-100.jpg'
var result2 = loadImg(src2)
Promi.all([result1, result2]).then(function (datas) {
console.log('all', datas[0])//<img src="/static/img/index/logo_new.png">
console.log('all', datas[1])//<img src="/545862fe00017c2602200220-100-100.jpg">
})
Promi.race([result1, result2]).then(function (data) {
console.log('race', data)//<img src="/545862fe00017c2602200220-100-100.jpg">
})
如果我们组合使⽤Promi,就可以把很多异步任务以并⾏和串⾏的⽅式组合起来执⾏
四、Async/Await简介与⽤法
异步操作是 JavaScript 编程的⿇烦事,很多⼈认为async函数是异步操作的终极解决⽅案。
1、Async/Await简介
async/await是写异步代码的新⽅式,优于回调函数和Promi。
async/await是基于Promi实现的,它不能⽤于普通的回调函数。
async/await与Promi⼀样,是⾮阻塞的。
async/await使得异步代码看起来像同步代码,再也没有回调函数。但是改变不了JS单线程、异步的本质。
2、Async/Await的⽤法
使⽤await,函数必须⽤async标识
await后⾯跟的是⼀个Promi实例
需要安装babel-polyfill,安装后记得引⼊ //npm i --save-dev babel-polyfill
function loadImg(src) {
const promi = new Promi(function (resolve, reject) {
const img = ateElement('img')
resolve(img)
}
reject('图⽚加载失败')
}
img.src = srcdeepa是什么意思
})
return promi
}
const src1 = '/static/img/index/logo_new.png'
const src2 = '/545862fe00017c2602200220-100-100.jpg'
const load = async function(){
const result1 = await loadImg(src1)
console.log(result1)
const result2 = await loadImg(src2)
console.log(result2)
}
laodload()
当函数执⾏的时候,⼀旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执⾏函数体内后⾯的语句。
五、Async/Await错误处理
await 命令后⾯的 Promi 对象,运⾏结果可能是 rejected,所以最好把 await 命令放在 atch 代码块中。atch错误处理也⽐较符合我们平常编写同步代码时候处理的逻辑。
async function myFunction() {
try {
await somethingThatReturnsAPromi();
} catch (err) {
console.log(err);
}
}
六、为什么Async/Await更好?
Async/Await较Promi有诸多好处,以下介绍其中三种优势:
1. 简洁
使⽤Async/Await明显节约了不少代码。我们不需要写.then,不需要写匿名函数处理Promi的resolve值,也不需要定义多余的data变量,还避免了嵌套代码。
2. 中间值
你很可能遇到过这样的场景,调⽤promi1,使⽤promi1返回的结果去调⽤promi2,然后使⽤两者的结果去调⽤promi3。你的代码很可能是这样的:
const makeRequest = () => {
return promi1()
.then(value1 => {
return promi2(value1)
.then(value2 => {
return promi3(value1, value2)
})
})
}
使⽤async/await的话,代码会变得异常简单和直观
const makeRequest = async () => {
const value1 = await promi1()
const value2 = await promi2(value1)
return promi3(value1, value2)
}
3.条件语句
下⾯⽰例中,需要获取数据,然后根据返回数据决定是直接返回,还是继续获取更多的数据。
const makeRequest = () => {
return getJSON()
.then(data => {
if (dsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
})
} el {
console.log(data)
return data
}
})
}
代码嵌套(6层)可读性较差,它们传达的意思只是需要将最终结果传递到最外层的Promi。使⽤async/await编写可以⼤⼤地提⾼可读性:
const makeRequest = async () => {
const data = await getJSON()
if (dsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
console.log(moreData)
return moreData
} el {
console.log(data)
return data
}
}
如果觉得⽂章对你有些许帮助,欢迎在点赞和关注,感激不尽!
参考⽂章
原⽂地址:/a/1190000016675466

本文发布于:2023-07-21 11:09:39,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/184186.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:代码   函数   需要
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图