es6-深刻理解promise

先講一下什麼是回調地獄->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的結果就能夠在後面的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的鏈式調用 上圖來描述下,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()
    }
}
複製代碼
相關文章
相關標籤/搜索