前言:最近在研究串接资料,刚好学习到了一个ES6的新用法,先来记录说明一下。
在此之前我们还要了解什么是同步与非同步
同步(synchronous):发一个请求,就要等待服务器的响应结束,然后才能发第二请求!中间这段时间就是 loading ;刷新的是整个页面。
异步(asynchronous):发一个请求后,无需等待服务器的响应,然后就可以发第二个请求!可以使用 Javascript 接受服务器的响应,然后使用 Javascript 来局部刷新。
来个比较如下:
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 对象