淺析Promise

聲明,只是簡單地提了提promise的基本使用,大牛繞道^_^

1.先看一個例子

你須要知道
1.axios是個庫
2.axios()返回一個Promise實例
3.你能夠把axios()理解爲$.ajax(),它們功能相近,只不過axios遵循promise規範ios

axios({
    url: '.'
}).then((resolve) => {
    console.log(resolve)
    return '我是第二個then'
}, (reject) => {
    console.log(reject)
}).then((resolve_2) => {
    console.log(resolve_2) // '我是第二個then'
}, (reject_2) => { 
    console.log(reject_2)
})

爲了防止你對這個鏈式調用看得眼花繚亂,我把這個給簡化一下ajax

axios({
    url: '.'
}).then(成功回調, 失敗回調)
  .then(成功回調2, 失敗回調2)

ok,準備好了嗎?下面咱們先來了解Promise的一些基本概念編程

2.Promise的基本概念

2.1Promise的做用

Promise是專門用來解決異步編程問題的,避免了層層嵌套的回調函數[Callback Hell]
下面是一個用傳統方法Callback Hell來寫的異步代碼
能夠很是明顯地看出來,Callback Hell的方式讓代碼的可讀性變得很是差axios

function loadImg(src, callback, fail) {
    let img = new Image()
    img.onload = function () {
        // 成功回調
        callback(img)
    }
    img.onerror = fail // 失敗回調
    img.src = src
}

let src = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
loadImg(src, function (img) {
    console.log(img.width)
}, function () {
    console.log('error')
})

2.2 Promise的三個狀態

  1. pending初始態,既不成功也不失敗
  2. fulfilled異步操做成功
  3. rejected異步操做失敗

Promise對象表明一個異步操做,且只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態,peding可轉化爲fulfilled與rejected,但fulfilled與rejected不可相互轉化promise

那知道這三個狀態又有什麼用咧?
OK,咱們看下面的代碼瀏覽器

axios({
    url: '.'
}).then(成功回調, 失敗回調)

axios({url: '.'})
異步操做成功表明了pending -> fulfilled -> then裏的第一個參數【成功回調】
異步操做失敗表明了pending -> rejected -> then裏的第二個參數【失敗回調】異步

3.then和catch的鏈式調用

由於 Promise.prototype.thenPromise.prototype.catch 方法返回promise 對象
因此它們能夠被鏈式調用。異步編程

OK,下面讓咱們仔細看一下回調觸發機制究竟怎樣的過程函數

axios({
    url: '.'
}).then(成功回調, 失敗回調)
  .then(成功回調2, 失敗回調2)

clipboard.png
是否是看的有點暈?不要緊,下面我來詳細解釋一下
1.異步操做成功 -> 進入第一個then的成功回調 -> 成功回調執行異步操做成功 -> 因爲又返回了一個Promise實例,其狀態因爲異步操做成功,由pending轉爲了fullfiled,因此還能夠再調用第二個then -> 進入第二個then的成功回調2
2.異步操做失敗-> 進入第一個then的失敗回調 -> 失敗回調執行異步操做成功 -> 因爲又返回了一個Promise實例,其狀態因爲異步操做成功,由pending轉爲了fullfiled,因此還能夠再調用第二個then -> 進入第二個then的成功回調2測試

你的問題:
1.爲何第一個then不論調用成功回調仍是失敗回調,第二個then都會調用成功回調2
答:由於第二個then調用進入哪一個回調函數,徹底是看第一個then返回的Promise是什麼狀態,換言之 —— 看異步操做成功與否

clipboard.png
舉一個栗子

axios({
    url: '.'
}).then((resolve) => {
    return xxx 
    // 注意xxx是個未聲明的變量
    // 瀏覽器會報錯,說明異步操做失敗了
    // 因此第一個then返回的Promise的狀態是 rejected
}, (reject) => {})
    .then((resolve_2) => {
    console.log(1)
}, (reject_2) => {
    // 因此第二個then只會調用它的第二個參數
    console.log(2)
})

2.你咋不提catch咧?
由於catch就是then的一個語法糖呀
catch等價於then只有第二個參數【失敗回調】的形式
上面的例子用catch,能夠這麼寫

axios({
    url: '.'
}).then((fulfilled) => {
    return xxx
    // 注意xxx是個未聲明的變量
    // 因此第一個then返回的Promise的狀態是 rejected
}, (rejected) => {
}).catch((rejected) => {
    // 因此直接進入catch
    console.log(2)
})

4.本身寫一個Promise

第一步

// 聲明一個函數 讓這個函數返回一個Promise實例
let setPromise = function () {
    return new Promise()
}

第二步

// new Promise()接受一個函數
// 規定這個函數必需要有兩個參數【成功回調,失敗回調】
let a = 0
let setPromise = function () {
    let fn = (x, y) => {
        setTimeout(() => {
            x('success') 
            // 必定要寫上異步操做成功後,會調用的回調函數
        }, 2000)
    }
    return new Promise(fn)
    // 在new的過程當中必定有一句fn.call(undefined, fulfilled, rejected)
}

第三步

// 寫的更裝逼點,順別把x,y換個名字【實際上是規定】
let setPromise = function () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        }, 2000)
    }) // 在new的過程當中必定有一句fn.call(undefined, fulfilled, rejected)
}

第四步

// 你要作什麼,就用then輸入到這個Promise實例裏面去
let promiseInstance = setPromise()
promiseInstance.then((success) => {
    console.log(success) // 'success'
}, () => { 
    console.log('失敗啦')
})

總結

let setPromise = function () {
    return new Promise((resolve, reject) => {
        // 你的異步代碼
        setTimeout(() => {
            resolve('success') // 給成功回調resolve傳遞一個參數 'success'
            console.log('測試一下') // 兩秒以後被執行
        }, 2000)
    })
}
// 你要作什麼,就用then輸入到這個Promise實例裏面去
let promiseInstance = setPromise()
promiseInstance.then((resolve) => {
    // 異步操做執行成功後執行
    console.log(resolve) // 'success'
    console.log('完美運行') // '完美運行'
}, () => {
    console.log('失敗啦')
})

5.最後

其實對於Promise和then有一個更具象化的理解
Promise的中文翻譯是承諾,then的中文翻譯是而後
因此,你能夠想象你去買橘子,結果店裏沒有進貨,店員對你Promise,只要他店裏到貨,then他就會通知你

相關文章
相關標籤/搜索