今天也是非同步资料请求的主题,复习一下在XHR(XMLHttpRequest)搭配Promise的用法!
如果一个function被作为参数传进另一个function,这种行为称为"Callback",
而作为参数的function 则称作"callback function"。
来看个例子:
doSomething(function(result){console.log(result);}, failureCallback)
假设doSomething()
执行的是,回传成功执行参数1(匿名函式),回传失败则执行参数2(failureCallback)。
被传入doSomething()
作为参数的两个function,就被称作callback function。
但当我们在函式里执行更多行为时,被嵌套的callback会越来越多层,然後程序码会变成这样的结构:
function failureCallback() {
console.log("failed");
}
doSomething(function(result) {
doSecondThing(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
这种 Callback被一层层嵌套,导致 程序码难以阅读和维护 的情况,就被称作 Callback Hell。*
或是例子不够生动,可以看看网路上的图片:
而为了避免产生callback Hell,现在多以使用promise的方式取代。
Promise 物件代表一个即将完成、或失败的非同步操作,以及它所产生的值。
引用自Promise - JavaScript | MDN
意思是, Promise 代表 在进行非同步请求时,成功取得的资料 或 失败的物件。
每当一个host要连结资料库(database management system),资料库应该回传一个Promise。
Promise 的建构式语法:
new Promise( /* executor */ function(resolve, reject) { ... } );
new是指产生一个新物件,所以这里会产生一个Promise的空物件,Promise 里面包含 resolve 或 reject 两种 callback function:
resolve
为成功取得的资料时,回传资料。reject
则会在失败时回传 error object。每当传入这两个参数,executor函式就会直接执行,并在成功时执行resolve
,在失败时执行reject
。
而promise很常被搭配使用两个function:
.then()
接住 resolve 的结果。.catch()
接住 reject 的结果。举例:
// 设定回传resolve的情况
let example = new Promise((resolve, reject) => {
resolve({type: "object"});
});
example.then((data)=>{console.log(data);});
在这个范例里,我们设定resolve
会回传一个object。
并且在执行.then()
後,把资料印出来。
// 设定回传reject的情况
let example = new Promise((resolve, reject) => {
reject(new Error("not allowed"));
});
example
.then((data)=>{console.log(data);})
.catch((error) => {console.log(error);});
而这个范例,是设定在reject
时,产生一个error object。
并在.catch()
抓到错误後,印出错误讯息。
promise的function是可以被串接起来的,被称为 Promise Chain。
let example = new Promise((resolve, reject) => {
resolve({ string : "Hello" });
});
example
.then((data)=>{console.log(data);})
.then(() => {console.log("HI");})
.catch((error) => {console.log(error);});
// output: { string : "Hello" } ; "HI"
这样的好处是,不管接续执行多少工作(.then()
),最後都只要指定一次失败的情况(.catch()
)。
而不必像早期的方式(Callback Hell的范例),传入许多次failureCallback
。
看完范例,最後来尝试实际应用Promise。
延续昨天显示气温的例子,今天试着用Promise改写内容。
附上程序码(和原来写法的差异,写在注解里):
const section = document.querySelector('section');
// 获得URL; 请记得将授权码字样替换掉!
var requestURL = 'https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-D0047-063?Authorization=授权码&limit=1&offset=7&format=JSON&elementName=T';
function loadData(url){
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.onload = function() {
// 如果正确获得资料,将资料写进resolve
if (request.status === 200) {
resolve(request.response);
} else {
// 如果失败,回传错误讯息
reject(Error('error code:' + request.statusText));
}
}
request.send();
});
}
// promise chain
loadData(requestURL)
.then((response)=>showWeather(response))
.catch((error)=>console.log(error));
function showWeather(jsonObj) {
var jsonT = jsonObj['records']['locations'][0]['location'][0]['weatherElement'][0]['time'][0]['elementValue'][0]['value'];
const temperature = document.createElement('h1');
temperature.textContent = "地点: 台北市, 现在气温: " + jsonT + ' °C ';
section.appendChild(temperature);
}
运行结果:
附上一些和Promise相关的问题:
你对 Promises 的经验?有用过相关的补强(ployfills)吗?
可以参阅这篇文章:[JavaScript] 解决在 IE 11 出现 'Promise' 未经定义的错误,言简意赅。
Promises 之於 callbacks 的优劣?
(待补充,优点上面有提到,缺点我要再找找资料。)
【如内文有误还请不吝指教>< 谢谢阅览至此的各位:D】
-----正文结束-----
昨天虽然完成了以永丰银行虚拟帐号付款方式进行结帐,但如果没有找个地方显示帐号,顾客也不知道要汇钱到那...
在介绍 gulp 之前 当然需要知道 gulp 它是什麽 简单来说 gulp 就是 基於node.j...
最後一个「价值Value」也是资料分析最重要的阶段,很重要是因为,只有在资料分析後可以产生比原始资料...
今天要来教大家数学的关系运算,也就是大於、等於、不等於...等等的,还有if的用法,就是假如某件事成...
大家早安~ 接下来就是到了我们实作二 - 资安攻击分析 on AWS,在那之前想先跟大家讨论 Q:『...