JavaScript ES6 promiss的理解。

  本着互聯網的分享精神,我將我對promise的理解分享給你們。 ajax

  JavaScript ES6的promise方法主要應用在處理異步函數返回的結果,注意他不是將異步函數轉換爲同步函數,而是等異步函數有結果時在調用相應的方法進行處理。數組

promise有如下方法

  then() - 它最多須要有兩個參數,第一個是成功後調用的方法,第二個是失敗後調用的方法。promise

  catch() - 失敗後調用的方法,他與then方法的失敗後調用的方法相似,可是使用上有些區別,等下我會用案例講解。服務器

  all() - 接收一個數組做爲參數,數組內可填寫異步函數,當全部的異步函數都執行完後,會返回一個promise執行後的數組。可是有一點須要注意的是,入過參數內有一個方法報錯那麼他就會報錯,並不會返回結果。異步

  race() - 他與all的方法相似也接受一個數組做爲參數(也是如若是數組內有一個方法報錯那麼他將會報錯,不會返回結果),可是有一點不一樣的是隻返回一個結果,那就是哪一個哪一個函數最早執行完成返回的哪一個結果。函數

  resolve() - 和then的第一個參數同樣,返回一個promise成功後調用方法。spa

  reject() - 和then的第二個參數同樣,返回一個promise失敗後調用的方法。code

萬惡的異步套回調。

  本案例中我使用定時器模擬ajax服務器異步請求。blog

function Fun(a, b, cb) {
    setTimeout(function () {
        cb(a + b)
    }, 1000)
}

Fun(1, 2 ,function (result) {
    console.log(result)
});
console.log(5); // 此時會先輸出5在輸出3

  在複雜一點的案例確定是回調套回調,這樣作確定是沒有錯代碼也會執行,可是邏輯上不是很清晰。ip

function Fun(a, b, cb) {
    setTimeout(function () {
        cb(a + b)
    }, 1000)
}

Fun(1, 2, function (result) {
    if (result > 1) {
        Fun(result, 2, function (result) {
            Fun(result, 3, function (result) {
                console.log('完成', result)
            })
        })
    }
});
console.log(5); // 此時會先輸出5在輸出  完成 8

 使用promise方法重寫上面的案例- then的使用

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
Fun(1, 2)
    .then(function (result) {
        if (result > 1) {
            return Fun(result, 2)
        }
    })
    .then(function (result) {
        if (result > 1) {
            return Fun(result, 3)
        }
    }).then(function (result) {
    console.log('完成', result)
});

使用then方法處理錯誤失敗

  then的第一個參數是處理Promise成功後使用的方法,第二個參數是Promise處理失敗後的方法,下面的案例我將會模擬錯誤。

  若是Fun函數內傳入的參數不是number類型,則觸發then方法的錯誤處理函數,也就是第二個函數,固然第一個函數就不會執行了。

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
Fun(1, '1')
    .then(function (result) {
        if (result > 1) {
            return Fun(result, 2)
        }
    }, function (err) {    //這個方法將會被執行,由於報錯了麼,很好理解吧
        console.log(err )
    })
    .then(function (result) {
        console.log('第二個then'); //輸出 第二個then 若是第一個then中的錯誤方法運用的穩當,對這裏是不會有影響的,可是我並無作相應的處理 只是輸出了err, result返回的是undefined,if中的方法也就不會執行了。
        if (result > 1) {
            return Fun(result, 3)
        }
    });

 

 使用 catch捕獲錯誤 - catch方法的使用

  then方法是從上向下運行,運行的中若是有發生錯誤的那麼then方法就會在發生錯誤哪裏中止運行,而且調用錯誤方法。注意:他與then的方法不一樣,then的處理機制處理完會繼續向下執行,而catch卻不會,會跳過未執行的then直接進入catch

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
Fun(1, 1)
    .then(function (result) {
        if (result > 1) {
            console.log(1)  // 1正常輸出。
            return Fun(result, '2') //這裏2不是number類型.
        }
    })
    .then(function (result) { // 因爲上面傳入的參數不是number類型,這裏的then 就會調用錯誤處理,也就是說會執行catch方法。
     console.log(2) // 不會執行
if (result > 1) { return Fun(result, 3) } }) .then(function (result) {
     console.log(3) // 不會執行 console.log(
'完成', result) }) .catch( function (err) {//會被執行 no number console.log(err) } );

  還有一種狀況主動拋出異常被catch捕獲

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
Fun(1, 1)
    .then(function (result) {
            if (result > 1) {
                if (result === 2) {
                    throw new Error('我要拋出錯誤由於我任性' + result) //主動拋出異常
                }
                console.log(1) 
                return Fun(result, 2) 
            }
        }
    )
    .then(function (result) { 
        console.log(2) 
        if (result > 1) {
            return Fun(result, 3)
        }
    })
    .then(function (result) {
        console.log(3)
        console.log('完成', result)
    })
    .catch(function (err) { // 我要拋出錯誤由於我任性2
        console.log(err)
    });

 

若是使用catch和then的第二個參數同時捕獲參數會怎麼樣呢?

  若是then方法有第二個參數那麼catch就不會執行,就會執行本身的第二個參數。能夠將catch理解爲接盤俠,若是then沒有處理錯誤的方法,那麼catch內的方法就會執行,若是同時沒有then的第二個方法和catch那麼就不會報錯,由於壓根就沒有錯誤的處理機制那麼就不會報錯了。

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
Fun(1, '1')
    .then(function (result) {
        if (result > 1) {
            return Fun(result, 2)
        }
    }, function (err) {   //執行 輸出 no number +12
        console.log(err + '12')   
    })
    .then(function (result) {
        console.log('第二個then'); // 執行輸出 第二個then  
        if (result > 1) {  //這裏不會執行由於沒有result 由於result 是undefined 若是在第一個then的處理方法內處理的穩當這裏就能夠執行。
            return Fun(result, 3)
        }
    })
    .catch(function (err) {  //這裏不會執行,由於每一個then有本身的處理方式,因此catch就不會執行。
        console.log(err + '我是catch的錯誤處理')
    });

 all和race方法的使用

  這種方法在咱們平常的項目中很常見,可是這種代碼使用起來過於繁瑣,那麼那有沒有更好的方法呢?

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
let resultList = [];
Fun(1, 2)
    .then(function (result) {
        resultList.push(result);
        return Fun(2, 3)
    })
    .then(function (result) {
        resultList.push(result)
        console.log(resultList)
    });

  使用all方法實現上面的案例,

  all方法接收一個數組做爲參數,數組內是方法,all會按照前後順序返回一個執行後的數組。

function Fun(a, b) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, 1000)
    })
}
var promise = Promise.all([Fun(1, 2), Fun(2, 3)]);
promise.then(function (resule) {
    console.log(resule)  //輸出 3 5
});

  race方法的使用

  race方法使用和all方法相似,可是返回結果不一樣,all方法返回所有結果,race返回的是最早被執行完成那個函數的結果。注意:race接收參數的數組內,若是有一個方法報錯,那麼就不會返回結果。

function Fun(a, b ,time) {
    return new Promise(function (resolve, reject) {
        if (typeof a !== 'number' || typeof b !== 'number') {
            reject(new Error('no number'))
        }
        setTimeout(function () {
            resolve(a + b)
        }, time)
    })
}
var promise = Promise.race([Fun(1, 2,1000), Fun(2, 3,200)]);
//race  那個結果先被獲得那麼就會返回第一個獲得的結果、可是若是總體有一個是錯誤的,那麼就會拋出異常而不會獲得結果。
promise.then(function (resule) {
    console.log(resule)  //輸出5
});

 reject和resolve的使用

reject返回的事一個拋出異常錯誤的方法。因此then的第二個函數或者是catch會被執行。

var promise = Promise.reject("我要拋出錯誤");

promise.then(function (reason) {
    // 未被調用
    console.log('reason')
}, function (reason) {
    console.log(reason);//執行,由於reject就是拋出異常的方法。
});

resolve返回的事一個正常執行的方法,因此then的第一個函數會被執行。

var promise = Promise.resolve("我是會被執行的")
promise.then(function (value) {
    console.log(value); // "我是會被執行的"
}, function (value) {
    // 不會被調用
    console.log(value)
});
相關文章
相關標籤/搜索