先講一下什麼是回調地獄->callback hell,給你們看一張圖片,回調地獄就是異步裏面套了異步,下面的異步請求依賴於上一個異步請求的結果,必須嵌套進去,放在回調裏面,就造成了回調地獄。爲了解決這一問題,es6出現了一個api,就是promise.es6
promise其實就是一個構造函數,咱們typeof promise ,就能得出一個"function",也能夠把它理解爲一個容器,這個容器中存放了一個異步任務。它有三種狀態,Pending(進行中),resolved(已成功),rejected(已失敗)。下面咱們建立一個promise容器ajax
Promise容器一旦建立,就開始執行裏面的代碼api
var fs = require('fs')
new Promise(function(){
fs.readFile('./a.txt','utf8,function(err,data)'{
if(err){
//失敗了,承諾容器中的任務失敗了
console.log(err)
}else{
//認可容器中的任務成功了
console.log(data)
}
})
})
複製代碼
下面咱們寫一個輸出,promise
console.log(1)
new Promise(function(){
console.log(2)
fs.readFile('./a.txt','utf8,function(err,data)'{
if(err){
//失敗了,承諾容器中的任務失敗了
console.log(err)
}else{
console.log(3)
//認可容器中的任務成功了
console.log(data)
}
})
})
console.log(4)
複製代碼
輸出的結果是什麼? 1 2 4 3 爲何會輸出這樣的呢?js執行順序不是從上到下麼?下面咱們簡單分析下: 先輸出1,緊接着遇到了new promise,當即執行,輸出2,咱們上邊提到了promise裏面的任務是一個異步,因此執行輸出4,當異步執行完後輸出3bash
在此強調下:promise自己不是異步,可是內部每每都是封裝一個異步任務。異步
下面咱們繼續,上邊提到了promise有成功和失敗的狀態,因此咱們把上邊new promise的代碼改寫下。函數
var p1=new Promise(function(resolve,reject){
fs.readFile('./a.txt','utf8,function(err,data)'{
if(err){
//失敗了,承諾容器中的任務失敗了
//把容器的Pending狀態變爲失敗Rejected
//調用reject就至關於調用了then方法的第二個參數函數
reject(err)
}else{
//認可容器中的任務成功了
//console.log(data)
//把容器的Pending狀態變爲成功resoved
//也就是說這裏調用的resolve方法實際上就是then方法傳遞的那個function
resolve(data)
}
})
})
複製代碼
上面的代碼描述了咱們圖中promise的概念,promise裏面有一個異步任務,默認的狀態pending成功了變成resoved,失敗了變成rejected。 那麼咱們如何使用它呢?ui
//p1就是promise
//當p1成功了而後(then)作指定的操做
//then方法接收的function就是容器中的resovle函數
p1
.then(function(data){
console.log(data)
},function(err){
console.log('讀取失敗了',err)
})
複製代碼
以上是promise的基礎語法, 我用圖來表示下url
下面咱們來講下解決回調地獄問題:p1
.then(function(data)){
//當p1讀取成功的時候,當前函數中return的結果就能夠在後面的then中function接收到,
//當你return 123後面就接收到123
// return 'hello' 後面就接收到'hello'
//沒有return 後面收到的就是undefined
//其實咱們真正用到的是能夠return 一個promise對象
//當return 一個Promise對象的時候,後續的then中的方法的第一個參數會做爲p2的resolve
// return 123
return p2
},function(err){
console.log(err)
})
.then(function(data){
console.log(data) //在此接收p2的返回值
})
var p2=new Promise(function()){
fs.readFile('./a.txt','utf8,function(err,data)'{
if(err){
reject(err)
}else{
resolve(data)
}
})
})
複製代碼
咱們也能夠多添加幾個then去返回多個new Promise,這個就是then的鏈式調用 上圖來描述下,spa
下面咱們封裝一個readFile,
var fs = require('fs')
function pReadFile(filePath) {
return new Promise(function (resolve,reject) {
fs.readFile(filePath,'utf8',function (err,data) {
if(err){
reject(err)
}else{
resolve(data)
}
}
}
}
pReadFile('./data/test.txt')
.then(function(data){
console.log(data)
return pReadFile('./data/a.txt')
})
.then(function(data){
console.log(data)
return pReadFile('./data/b.txt')
})
.then(function(data){
console.log(data
})
複製代碼
以上是一個簡單完整的小例子。 如今咱們封裝一個promise的ajax方法。
function pGet(url,callback){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest()
xhr.onload = function(){
callback && callback(JSON.parse(pGet.responseText))
resolve(JSON.parse(pGet.responseText))
}
xhr.onerror = function(){
reject(err)
}
xhr.open("get",url,true)
xhr.send()
}
}
複製代碼