今天要来介绍为什么要使用 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 是做甚么~
很明显,这个就是你针对他们的 API 要资料以后,他会回传给你 result 的 json 格式资料。
内容就如同他们官网的显示,会随机产生使用者资料给你。
那我们实际来执行看看!
的确就跟预期的一样!有出现官网上所说的资料格式~
状况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 的资料会是怎么样呢?
答案:
答案就是还是维持空物件喔!
原因很简单,因为非同步的事件会先放到事件伫列,等其他同步的程式码执行完之后,再依顺序执行。
所以这边 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);});
各位也可以练习看看这样子的写法喔!
那其实这样写,每次重新整理阿
你会发现都会取得随机不同的资料,如果我希望再取得第一次资料以后,又再取得同一个人的资料的话该怎么半呢?
我们可以看到他的官方文件中,有一个可以带入 seed 的参数,也就是每一笔使用者资料,都有一个特定的 seed 参数。
状况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); });});
好~这样就可以完成我们的需求对吧!
但又要第三次呢?第四次呢?
发现问题了吗? 如果我们要做特定的处理,就必须等到非同步结束以后才能进行,这样会造成越来越多 巢状 以及程式码繁乱不好维护的问题!
而使用 Promise 的好处之一就是可以解决这个问题~
那这边也来简单介绍一下,非同步的常见问题
回呼地狱(Callback Hell)写法不一致无法同时执行(jQuery 有并行的写法,但并不直觉)那我们使用 axios 这个 Promise 套件进行刚刚取得远端资料的效果并同时解决 1 / 2 / 3 的问题
axios.get(url) .then((res) => { console.log(1, res); });
当使用 axios 的时候首先要先决定要使用 get 还是 post,之后最简单的一样就是只带入 url 。
然后利用 then 这个方法去串接,确保非同步行为已经完成!
写法一致 + 避免回呼地狱:
那么如果要像刚刚一样,在第一次取完以后要进行第二次非同步事件,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); });
同时发出请求
Promise 里面有一个 all 的语法,会同时分别针对不同的 url 进行请求,并且等到都完成拿到结果之后,在进行下一步。
Promise.all([axios.get(url), axios.get(url)]) .then(([res1, res2]) => { console.log(1, res1); console.log(2, res2); });
透过阵列的方式传入 非同步行为,并且回传一个阵列包含两个非同步行为的结果。
以上就是使用 Promise 的原因,以及一些简单的範例介绍,如果没有问题的话就可以继续往后续的文章噜!汪汪~