Javascript 进阶 11-1 为什么需要 Promise

今天要来介绍为什么要使用 Promise

Promise 的使用时机就是适合来解决非同步的事件,非同步的事件通常都是 ajax 的事件,但其实除了 ajax 以外还有其他的喔~!

例如说 setTimeout 也是一种非同步事件,不过还是以大家最熟悉的 ajax 事件来进行说明~!

const url = 'https://randomuser.me/api/'; $.ajax({    url: url}).done(function (res) {    console.log(res);});

可以看到这个是很简易的 jQuery ajax 的写法,我只有撰写了 url 向远端位置请求资料,然后再把资料印出来!

当然 jQuery 官网也有很多种写法~例如 直接在属性中添加 success 属性的,或是加入不同的 Content-Type 的等等。

$.ajax({  url: 'https://randomuser.me/api/',  dataType: 'json',  success: function(data) {    console.log(data);  }});

但目的都是为了从远端取得资料回来~

那么我们再来看看关注现在要打的这只 API 是做甚么~

http://img2.58codes.com/2024/20121770ENEx7WbI7e.png

http://img2.58codes.com/2024/20121770MbN8HxbyPc.png

很明显,这个就是你针对他们的 API 要资料以后,他会回传给你 result 的 json 格式资料。

内容就如同他们官网的显示,会随机产生使用者资料给你。

那我们实际来执行看看!

http://img2.58codes.com/2024/20121770B38PUvhZYD.png

的确就跟预期的一样!有出现官网上所说的资料格式~

状况1

那么现在我们来修改一下程式码~变成下面这样

const url = 'https://randomuser.me/api/'; let data = {};$.ajax({    url: url,}).done(function (res) {    console.log(res);    data = res.results;});console.log(data);

各位觉得 data 的资料会是怎么样呢?

答案:

http://img2.58codes.com/2024/20121770HicssAMDeD.png

答案就是还是维持空物件喔!

原因很简单,因为非同步的事件会先放到事件伫列,等其他同步的程式码执行完之后,再依顺序执行。

所以这边 ajax 事件虽然有先放到事件伫列中,但还没跟远端取回资料,自然就还没有办法再最后面的 log 给印出来。

那么要如何才能正确印出来呢?

最快速简单的做法就是把 log 移进去 done 的 function Block 里面。

const url = 'https://randomuser.me/api/';         let data = {};$.ajax({    url: url,}).done(function (res) {    console.log(res);    data = res.results;    console.log(data);});

http://img2.58codes.com/2024/20121770GjPQYMxxdJ.png

各位也可以练习看看这样子的写法喔!

那其实这样写,每次重新整理阿

你会发现都会取得随机不同的资料,如果我希望再取得第一次资料以后,又再取得同一个人的资料的话该怎么半呢?

我们可以看到他的官方文件中,有一个可以带入 seed 的参数,也就是每一笔使用者资料,都有一个特定的 seed 参数。

http://img2.58codes.com/2024/20121770lgWJb9G7Ak.png

状况2

我们需要在第一次取得资料之后,又需要在执行完之后取得第二次的资料

那我们的写法就会是~

const url = 'https://randomuser.me/api/'; let data = {};$.ajax({    url: url,}).done(function (res) {    console.log(res);    data = res.results;    const seed = res.info.seed;    console.log('seed', seed);    console.log('data', data);    console.log('res', res);    $.ajax({        url: `${url}?seed=${seed}`,    }).done(function (res2) {        console.log('res2', res2);        const res2Seed = res2.info.seed;        console.log(seed === res2Seed);    });});

http://img2.58codes.com/2024/20121770HdfbvdeE8i.png

好~这样就可以完成我们的需求对吧!

但又要第三次呢?第四次呢?

发现问题了吗? 如果我们要做特定的处理,就必须等到非同步结束以后才能进行,这样会造成越来越多 巢状 以及程式码繁乱不好维护的问题!

而使用 Promise 的好处之一就是可以解决这个问题~

那这边也来简单介绍一下,非同步的常见问题

回呼地狱(Callback Hell)写法不一致无法同时执行(jQuery 有并行的写法,但并不直觉)

那我们使用 axios 这个 Promise 套件进行刚刚取得远端资料的效果并同时解决 1 / 2 / 3 的问题

axios.get(url)    .then((res) => {        console.log(1, res);    });

当使用 axios 的时候首先要先决定要使用 get 还是 post,之后最简单的一样就是只带入 url 。

然后利用 then 这个方法去串接,确保非同步行为已经完成!

http://img2.58codes.com/2024/201217700LKJiaA9uk.png

写法一致 + 避免回呼地狱:

那么如果要像刚刚一样,在第一次取完以后要进行第二次非同步事件,Promise 的行为会先 return 第二次的请求开头,并且在下一次的 then 做接收。

axios.get(url)    .then((res) => {        console.log(1, res);        const seed = res.data.info.seed;        return axios.get(`${url}?seed=${seed}`);    })    .then((res) => {        console.log(2, res);    });

http://img2.58codes.com/2024/20121770274Bj7tpco.png

同时发出请求

Promise 里面有一个 all 的语法,会同时分别针对不同的 url 进行请求,并且等到都完成拿到结果之后,在进行下一步。

Promise.all([axios.get(url), axios.get(url)])    .then(([res1, res2]) => {        console.log(1, res1);        console.log(2, res2);    });

透过阵列的方式传入 非同步行为,并且回传一个阵列包含两个非同步行为的结果。

http://img2.58codes.com/2024/20121770xHIJ0TqJJO.png

以上就是使用 Promise 的原因,以及一些简单的範例介绍,如果没有问题的话就可以继续往后续的文章噜!汪汪~


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章