es6-深入理解promise

丸子沒櫻桃發表於2018-12-11

先講一下什麼是回撥地獄->callback hell,給大家看一張圖片,回撥地獄就是非同步裡面套了非同步,下面的非同步請求依賴於上一個非同步請求的結果,必須巢狀進去,放在回撥裡面,就形成了回撥地獄。為了解決這一問題,es6出現了一個api,就是promise.

es6-深入理解promise
promise其實就是一個建構函式,我們typeof promise ,就能得出一個"function",也可以把它理解為一個容器,這個容器中存放了一個非同步任務。它有三種狀態,Pending(進行中),resolved(已成功),rejected(已失敗)。

es6-深入理解promise

下面我們建立一個promise容器

Promise容器一旦建立,就開始執行裡面的程式碼

var fs = require('fs')
new Promise(function(){
    fs.readFile('./a.txt','utf8,function(err,data)'{
        if(err){
            //失敗了,承諾容器中的任務失敗了
            console.log(err)
        }else{
            //承認容器中的任務成功了
            console.log(data)
        }
        
    })
})
複製程式碼

下面我們寫一個輸出,

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,當非同步執行完後輸出3

在此強調下: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。 那麼我們如何使用它呢?

//p1就是promise
//當p1成功瞭然後(then)做指定的操作
//then方法接收的function就是容器中的resovle函式
p1
    .then(function(data){
        console.log(data)
    },function(err){
        console.log('讀取失敗了',err)
    })
複製程式碼

以上是promise的基礎語法, 我用圖來表示下

es6-深入理解promise
下面我們來說下解決回撥地獄問題:

p1
.then(function(data)){
    //當p1讀取成功的時候,當前函式中return的結果就可以在後面的thenfunction接收到,
    //當你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的鏈式呼叫 上圖來描述下,

es6-深入理解promise

下面我們封裝一個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()
    }
}
複製程式碼

相關文章