0


JavaScript异步编程这一篇足够啦

JavaScript异步编程

我们编写的同步JavaScript代码是一系列按照顺序立即执行的指令。比如,使用JavaScript做简单的DOM处理,可能会写出如下的代码。

const header = document.getElementById('heading');

header.innerHTML ='Hey!';

这些就是指令。“去选择ID为heading的元素。然后,把那个元素内的HTML设为‘Hey’吧。”这一切都是同步的。一项操作在执行的过程中,不执行其他任何操作。

在现代web中,离不开异步任务。这种任务通常需要等到其他作业结束才能完成。我们可能需要访问数据库,可能需要缓存视频或者音频流内容,可能需要从API中获取数据。在JavaScript中,异步任务不阻塞主线程。

在等待API返回数据的时段内,JavaScript是空闲的,可以去做其他事。过去几年,JavaScript取得了长足的发展,进一步简化了异步操作的处理机制。

1 使用fetch处理简单的promise

以前,请求REST API是一件非常复杂的事情,为了把数据加载到应用中,要编写20多行嵌套的代码。后来,fetch()函数的出现拯救了我们。感谢ECMAScript委员会的这一善举。

我们从randomuser.me API获取一些数据。这个API提供了电子邮件地址,姓名,电话号码,地理位置等成员信息,可用作虚拟数据。

fetch函数只接受一个参数,即资源的URL。

console.log(fetch('https://api.randomuser.me/?nat=US&results=1'));

在控制台中可以看到输出了一个挂起的promise。promise为理解JavaScript中的异步行为提供了一种方式。promise是一个对象,表示异步操作的状态是挂起、已完成或是失败。这就好像是浏览器告诉你,“嗨,我会尽自己所能获取这个数据。不管成功与否,我都会回过头来告诉你进展的。”

再回来看fetch的结果。挂起的promise表示获取数据之前的状态。我们要串接一个名为.then()的函数。这个函数接受一个回调函数,在前一步操作执行成功后运行。也就是先获取一些数据,然后再做其他操作。

这里我们想做的其他操作是把响应变成json格式。

fetch('https://api.randomuser.me/?nat=US&results=1').then(res=>{
    console.log(res.json());});

then方法再promise得到成功处理后调用回调函数。不管回调函数返回什么,都将作为下一个then函数的参数。因此,我们可以串接多个then函数处理成功的promise。

fetch('https://api.randomuser.me/?nat=US&results=1').then(res=> res.json()).then(json=> json.results).then(console.log).catch(console.error);

首先,使用fetch向randomuser.me发起一个GET请求。如果请求成功,把响应主题转换成json格式。接下来,返回得到的json结构,再把结果发给console.log函数,输出到控制台。最后有个catch函数,再fetch没有得到成功处理时调用指定的回调。在从randomuserm.me获取数据的过程中出现的所有错误都将根据这个回调进行处理。这里,我们只是使用console.error把错误输出到控制台。

2 async/await

处理promise的另一种常用的方式是创建异步函数。一些开发者倾向使用异步函数句法,因为所用的句法较熟悉,就像同步函数的代码一样。此时,我们不等待promise成功处理后返回结果再调用一系列then函数了,而是让异步函数暂停只想函数中的代码,知道promise处理成功。

下面再发起一个API请求,不过这一次把整个过程放到一个异步函数中。

constgetFakePerson=async()=>{let res =awaitfetch('https://api.randomuser.me/?nat=US&results=1');let{ results }= res.json();
    console.log(results)};getFakePerson();

注意,getFakePerson函数是使用async关键字声明的。这样定义的才是异步函数,才会在成功处理promise之前暂停执行后续代码。promise调用前面要加上await关键字,让异步函数等待promise得到成功处理。上述代码完成的任务与前一节使用then函数的那段代码完全一样。好吧,几乎完全一样……

constgetFakePerson=async()=>{try{let res =awaitfetch('https://api.randomuser.me/?nat=US&results=1');let{ results }= res.json();
        console.log(results)}catch(error){
        console.log(error);}};getFakePerson();

好了,现在这段代码完成的任务真正与前一节使用then函数的那段代码完全一样了。如果fetch调用处理成功,把结果输出到控制台;如果不成功,使用console.error把错误输出到控制台。使用async和await时,要把promise调用放在try……catch块中,处理promise失败时可能出现的错误。

3 构建promise

异步请求的结果有两种可能:一切如我们所愿,或者出现错误。成功和失败的请求有多种不同的类型。例如,我们可以不断尝试获取数据,直至成功。收到的错误也可能有多种类型。promise提供了一种处理方式,可以把这种复杂的情况简化为一次成功或失败。

下面的getPeople函数返回一个新的promise。这个promise向API发起请求,如果成功,加载数据;如果不成功,返回错误。

constgetPeople=count=>newPrimise((resolves, rejects)=>{const api =`https://api.randomuser.me/?nat=US&results=${count}`;const resquest =newXMLHttpRequest();
        request.open('GET', api);
        request.onload=()=>
            request.status ===200?resolves(JSON.parse(request.response).results):reject(Error(request.statusText));
        request.onerror=err=>rejects(err);})

这种情况下,虽然创建promise,但并没有使用。若想使用这个promise要调用getPeople函数,传入要加载的成员数量。我们还可以串接then函数,在这个promise处理成功后做些操作。如果promise被拒,相关细节会发回catch函数或async/await 语法中的catch块。

getPeople(5).then(members=> console.log(members)).catch(error=>console.error(`getPeople failed: ${error.message}`))

promise简化了异步请求的处理过程,这是一件好事,因为在JavaScript中经常需要处理异步任务。对现代的JavaScript工程技术人员来说。扎实的理解异步行为是必备技能。


本文转载自: https://blog.csdn.net/leoStudyWork/article/details/126692605
版权归原作者 leoStudyWork 所有, 如有侵权,请联系我们删除。

“JavaScript异步编程这一篇足够啦”的评论:

还没有评论