異步就是比較耗時的操做,CPU緩存的速度是最快的,而後是內存,而後是硬盤,因此從硬盤上讀取文件是很是慢的,js認爲從硬盤上讀取文件是一個異步操做;另一種是網絡請求,這種也是異步的;操做dom節點也是很是耗時的,但倒是同步操做,由於做爲異步來處理比較麻煩。node
promise就是一個承諾,在js中就是承諾過段時間會返回一個結果,而這個過段時間就指的是異步操做。webpack
promise本質上是一個有限狀態機,狀態機指的是根據特定的條件按照必定的順序進行轉換,並且過程不可逆。每一個promise實例都有三種狀態:pending、resolve、reject。在狀態機中,須要某些條件才能將本身的狀態觸發。git
狀態只有兩種:從初始狀態到成功:pending->resolve;從初始狀態到失敗:pending->reject。promise實例狀態機狀態的變化會觸發promise原型上的then或catch方法的執行github
DOM規範是運行在瀏覽器上的規範,好比navigator,只在dom上有,在node上沒有;而ECMAScript規範,不只在瀏覽器中可使用,也能夠在node.js中使用。web
如何構建一個promiseajax
構建一個promise實例須要給promise構造函數傳入一個有兩個形參的函數,第一個形參運行後會讓promise實例處於resolve狀態,因此通常用resove表示成功狀態;第二個形參運行後會讓promise實例處於reject狀態,因此通常用reject表示失敗狀態。new出來的promise實例,有兩個方法(then,catch,then捕獲成功的操做,catch捕獲失敗的操做。),而且能夠鏈式調用。在使用的時候,要將then放在catch的上面,這是由於then裏的錯誤也能夠在catch中捕獲到,如代碼所示:json
let promiseInstance = new Promise((resolve,reject) =>{ setTimeOut(() => { resolve('this is resolve.') }) }) promiseInstance .then((value)=>{console.log(value)}).catch((err)=>{console.error(err)})
promise是處理異步的,而網絡請求是異步最多見的場景,因此能夠用promise封裝一個網絡請求的方法,因此不少時候promise的實例是做爲函數的返回值是,調用函數後能夠對返回值的Promise對象進行相應的操做api
function ajaxPromise(){
return new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open('get',queryUrl,true);
xhr.send(null);
xhr.onReadyStatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
resolve(xhr.responseText);
}else{
reject(xhr.responseText)
}
}
}
}) }
ajaxPromise('http://api.github.com/')
.then((value) => {
console.log(value);
})
.catch((err) => {
console.error(err)
})
then與catch的使用promise
狀態機的狀態是不可逆的,因此執行了resolve方法,就算再執行reject方法,也不會有效果了。瀏覽器
promise的api
promise實例上的方法
promise.prototype.then()
promise.prototype.catch()
promise構造函數上的方法
promise.all(Array) 返回一個promise,等待參數中全部的promise都處於resolve狀態後會觸發返回的promise實例的resolve狀態
promise.race(Array) 返回一個promise,參數中第一個執行完成的狀態決定出發哪一個函數
promise.resolve() 馬上返回一個resolve狀態的實例
promise.reject() 馬上返回一個reject狀態的實例
let promise1 = new Promise((resolve,reject)=>{ setTimeout(resolve,1000,'success1') }) let promise2 = new Promise((resolve,reject)=>{ setTimeout(resolve,1000,'success12') }) let promise3 = new Promise((resolve,reject)=>{ setTimeout(resolve,1000,'success3') }) Promise.all([promise1, promise2, promise3]).then((value)=>{ console.log(value) }).catch((err)=>{ console.error(err) })
tips:setTimeOut的第三個參數,是第一個函數參數執行的時候,要傳入的參數
promise.then的執行時機
promise.resolve是處理異步問題的,因此會先把同步的代碼執行完,再執行promise.resolve返回實例的then或catch的代碼
而Promise構造函數是同步的,then方法是異步的。setTimeOut的執行時機是最晚的
promise並非處理異步最好的方法,好比回調金字塔的問題並無解決,只是看起來更清晰了。解決異步最好的方法是async
generator
有點像一個函數內部有多個函數,是一個狀態機,yield生成
function* genFunc(){ yield 'hello';
yield 'generator';
yield '!'
return 'end'//generator不建議使用return
}
generator返回的不是返回值,也不是一個生成的內容,而是一個迭代器,迭代器是一個可遍歷的對象,迭代器有個next方法。經過for-of循環遍歷迭代器
連續運行的generator
function* genFunc(initValue){ let first = yield new Promise((resolve,reject)=>{ setTimeOut(resolve,1000,'1'+initValue) }) let second = yield new Promise((resolve,reject)=>{ setTimeOut(resolve,1000,'2-'+first) }) let third = yield new Promise((resolve,reject)=>{ setTimeOut(resolve,1000,'3-'+second) }) let genHandler = genFunc(1) genHandler.next().value. then((value) => { genHandler.next(value).value. then((value) => { then((value) => { console.log(value); }) }) }) }
co庫與async函數
import co from 'co'
上述代碼中依然有回調金字塔,能夠用co庫解決
co(genFunc(1)).then((value) => {console.log(value)})//2-11
async至關因而generator+promise+co,是es7的新語法,目前沒有瀏覽器實現,因此須要用webpack+babel編譯一下才能夠運行。
如何同步異步請求,即兩次請求,異步執行,如何在兩次請求都執行完成的狀況下執行後續程序
function request(content){ setTimeout(()=>{ document.body.append(content) },Math.floor(Math.random()*1000)) //時間控制爲不肯定
} request('hello') request('world') //如何在兩次request完成後執行代碼。可使用promise.all,只要兩個異步有一個完成就能夠,可使用promise.race
docuement.body.append('finished')
如何處理回調嵌套回調
//珠峯課堂是先去服務端拿取token,而後再去拿課程
fetch('https://ketang.zhufengpeixun.cn/token') .then(response => { response.json().then(tokenJson =>{ const token = tokenJson fetch('https:ketang.zhufengpeixun.cn/course') .then( response =>{ response.json().then(tokenJson =>{ } }) }) })
promise定義:用於異步計算,表明一個當前、將來或永遠不可用的值
//promise中的代碼段被直接執行了
const promise = new Promise((resolve,reject){ document.body.append('hello') }) const a = () =>{ document.body.append('world') } a(); //執行結果是hello world
//用promise表示一個將來的值
function resolve_example(){ const promise = new Promise((resolve,reject)=>{ document.body.append('start.....'); setTimeout(()=>{//promise表明了一個將來值
resolve('done') },2000) }) return promise; } const promise = resolve_example(); //獲得一個將來完成的值,此處data是異步返回的部分
promise.then(data => { document.body.append(data) })
promise有三種狀態,當被new出來的時候屬於pending狀態,使用resolve則是fulfill狀態,使用reject則是fail狀態
Executor是構造Promise的惟一參數,在promise構造的時候會被立刻執行