前言:
最近在研究串接資料,剛好學習到了一個ES6的新用法,先來記錄說明一下。
在此之前我們還要了解什麼是同步與非同步
同步(synchronous):發一個請求,就要等待服務器的響應結束,然後才能發第二請求!中間這段時間就是 londing ;刷新的是整個頁面。
異步(asynchronous):發一個請求後,無需等待服務器的響應,然後就可以發第二個請求!可以使用 Javascript 接受服務器的響應,然後使用 Javascript 來局部刷新。
來個比較如下:
Async | sync |
---|---|
one at a time | more one at a time |
執行了就馬上換下一個指令 | 第一個執行完才執行下一個 |
Async Actions
- click, AJAX, SetInterval
- 解決方法, callback , promises, async await (這一次不討論,因為他是promises 的簡寫)
先說說callback,就是在function裡面再執行一個function 這是目前傳統用法來解決同步非同步的事情。
var btn =document.querySelector('#btn');
var doIt = function() {
alert("you triggered " + this.id);
};
btn.addEventListener("click", doIt);
我們可以說 doIt 就是一個 callback 函式,
回到今天想要講的 Promise :100:
- ES6新語法
- Promise 物件代表一個即將完成、或失敗的非同步操作, 以及它所產生的值。
- return resolve or reject (用到了兩個參數)
- ES6 Promise的實作中,會確保Promise物件一實體化後就會固定住狀態,要不就是"已實現",要不就是"已拒絕"
附註:resolve 和 reject 是參數 大概會是長像下面一樣:
const promise = new Promise(function(resolve, reject) {
// 成功時
resolve(value)
// 失敗時
reject(reason) });
promise.then(function(value) {
// on fulfillment(已實現時)
}, function(reason) {
// on rejection(已拒絕時)
})
//http://eddychang.me/blog/javascript/88-promise-basic-usage.html
記住我們為什麼要把 Promise 用在 Ajax 上面:
Ajax 是屬於一個透過 JavaScript 技術名稱,用於取得遠端資料;而 Promise 則是一個語法,專門用來處理非同步行為,並不是專門用來處理 Ajax 使用,所以兩者是不同的。
中文翻譯意思:
如果想等 A 結束之後再進行 B..?
用一個生活化例子就是,我們去百貨公司美食街吃東西,點完餐店員會給你一個小圓盤,等那圓盤動了,就可以去拿吃的。 結果成功就是 resolve ,失敗了就是rejected
Promise:
如果成功的話… 如果失敗的話… (resolve)<–> (reject)
先備知識: 函式建構式要先了解比較好喔! JavaScript 建構式
new Promise
代表的是建立一個 Promise 物件,function(resolve, reject){}
代表的是建構式裡面包含的執行函式( executor function ),執行函式包含,resolve、reject
,這兩個函式作為參數,當事件成功時便會回傳resolve
裡面的值,反之當事件失敗便會回傳reject
裡面的值。
接下來說個例子, 我們先設定攻擊的大絕招,成功之後(resolve) 會發生什麼事
let Bigtrick = new Promise( (resolve,reject)=>{
// 可能是⼀個需要花時間的動作..
setTimeout(()=> resolve('火之呼吸'),3000);
// setTimeout(function resolve(){
// resolve('火之呼吸');
// },3000)
});
Bigtrick
.then((skill)=>console.log(`使用招式:${skill}`)) //promise成功
.catch((err)=>console.log(`${err}無法使用`))//promise失敗
而 Bigtrick().then
的 then 代表了可以接收 Bigtrick()
這個 Promise 完成時,可以接受到回傳的值,如果回傳的值為錯誤時,則可以用 .catch 去做錯誤的值接收,.then 是可以一直串接下去的。這個行為叫做 Promise Chain
setTimeout()用法
MDN 定義 setTimeout() 的作用 是在延遲了某段時間 (單位為毫秒) 之後,才去執行「一次」指定的程式碼
接下來製作一個小遊戲, 範例網址 點擊一個按鈕連擊 5次以上在三秒之內,成功執行後會產生招式名稱。
我們先找到 按鈕和印出畫面的 dom,然後做出點擊時會發生的事件:數字chi變數=點擊次數出現在畫面
let chi =0;
let i =0;
let hitButton =document.getElementById('hitButton');
let result =document.getElementById('result');
hitButton.onclick=function(e){
e.preventDefault();
chi +=1;
hitButton.innerHTML =`集氣 ${chi}次 `;
}
那我們利用 new Promise()實作,要在三秒以內,點擊數超過5次才會出現 水之呼吸(利用 setTimeout 方法)
let bigSkill =new Promise((resolve,reject)=>{
setTimeout(()=>{
if(chi>=5){
resolve('水之呼吸!!');
}else{
reject('水之呼吸!!');
};
},3000);
});
成功達成條件後(點擊超過五次)resolve 就連上.then, 失敗 reject 就是被 catch 接到
bigSkill
.then( skill => result.innerHTML =`發動招式:${skill}`)
.catch( err => result.innerHTML =`${err} 無法使用`)
畫面如下:
其實 promise 不是必要,在以前沒有 promise 的時候也是可以做到非同步的事。在 promise 之前,可以用 callback 的方式來處理,但如果連續的處理的事情多,callback 就容易一層包一層,程式碼會變得不容易閱讀,俗稱「callback hell」
這樣是我真的對 callback function 怕怕的原因,函式包函式 ,腦袋都要昏了。
而 promise 的出現,可以簡化 callback 的流程,用 then .. then .. 的方式來解決 callback hell 的狀況喔。
資料來源:
五倍速紅寶石 使用 Promise 處理非同步 Promise 對象