[面試專題]JS異步之Promise,Generator,Async

JS異步之Promise,Generator,Async


Promise

  1. 解決的問題:回調地獄segmentfault

  2. Promise規範:promise

  • promise有三種狀態,等待(pending)、已完成(fulfilled/resolved)、已拒絕(rejected).Promise的狀態只能從「等待」轉到「完成」或者「拒絕」,不能逆向轉換,同時「完成」和「拒絕」也不能相互轉換.異步

  • promise 必須提供一個 then方法以訪問其當前值、終值和據因。promise.then(resolve, reject),resolve 和 reject都是可選參數。若是 resolve 或reject 不是函數,其必須被忽略.async

  • then 方法必須返回一個 promise 對象.函數

  1. 使用:code

  • 實例化promise對象須要傳入函數(包含兩個參數),resolve和reject,內部肯定狀態.resolve和reject函數能夠傳入參數在回調函數中使用.
    resolve和reject都是函數,傳入的參數在then的回調函數中接收.對象

var promise = new Promise(function(resolve, reject) {
    setTimeout(function(){
        resolve('好哈哈哈哈');
    });
});
promise.then(function(val){
  console.log(val)
  })
  • then接收兩個函數,分別對應resolve和reject狀態的回調,函數中接收實例化時傳入的參數.get

promise.then(val=>{
  //resolved
},reason=>{
  //rejected
})
  • catch至關於.then(null, rejection)
    當then中沒有傳入rejection時,錯誤會冒泡進入catch函數中,若傳入了rejection,則錯誤會被rejection捕獲,並且不會進入catch.此外,then中的回調函數中發生的錯誤只會在下一級的then中被捕獲,不會影響該promise的狀態.generator

new Promise((resolve,reject)=>{
   throw new Error('錯誤')
 }).then(null,(err)=>{
   console.log(err,1);//此處捕獲
 }).catch((err)=>{
   console.log(err,2);
 });
 // 對比
 new Promise((resolve,reject)=>{
   throw new Error('錯誤')
 }).then(null,null).catch((err)=>{
   console.log(err,2);//此處捕獲
 });
 // 錯誤示例
 new Promise((resolve,reject)=>{
   resolve('正常');
 }).then((val)=>{
   throw new Error('回調函數中錯誤')
 },(err)=>{
   console.log(err,1);
 }).then(null,(err)=>{
   console.log(err,2);//此處捕獲,也可用catch
 });
  • 二者不等價的狀況:
    此時,catch捕獲的並非p1的錯誤,而是p2的錯誤,回調函數

p1().then(res=>{ 
        return p2()//p2返回一個promise對象 
     }).catch(err=> console.log(err))
  • 一個錯誤捕獲的錯誤用例:
    該函數調用中即便發生了錯誤依然會進入then中的resolve的回調函數,由於函數p1中實例化promise對象時已經調用了catch,若發生錯誤會進入catch中,此時會返回一個新的promise,所以即便發生錯誤依然會進入p1函數的then鏈中的resolve回調函數.

function p1(val){
    return new Promise((resolve,reject)=>{
      if(val){
        var len = val.length;//傳入null會發生錯誤,進入catch捕獲錯誤
        resolve(len);
      }else{
        reject();
      }
    }).catch((err)=>{
      console.log(err)
    })
  };
  p1(null).then((len)=>{
      console.log(len,'resolved');
  },()=>{
    console.log('rejected');
  }).catch((err)=>{
    console.log(err,'catch');
  })
  • Promise回調鏈:

    • promise可以在回調函數裏面使用 return 和 throw, 因此在then中能夠return出一個promise對象或其餘值,也能夠throw出一個錯誤對象,但若是沒有return,將默認返回 undefined,那麼後面的then中的回調參數接收到的將是undefined.

function p1(val){
    return new Promise((resolve,reject)=>{
      val==1?resolve(1):reject()
    })
  };
  function p2(val){
    return new Promise((resolve,reject)=>{
      val==2?resolve(2):reject();
    })
  };
  let promimse = new Promise(function(resolve,reject){
           resolve(1)
  })
    .then(function(data1) {
         return p1(data1)//若是去掉return,則返回undefined而不是p1的返回值,會致使報錯
    })
    .then(function(data2){
        return p2(data2+1)
    })
    .then(res=>console.log(res))

Generator函數:

  • generator函數使用:
    一、分段執行,能夠暫停

二、能夠控制階段和每一個階段的返回值
三、能夠知道是否執行到結尾

function* g() {
    var o = 1;
    yield o++;
    yield o++;
}
var gen = g();

console.log(gen.next()); //  Object {value: 1, done: false}

var xxx = g();

console.log(gen.next()); // Object {value: 2, done: false}
console.log(xxx.next()); // Object {value: 1, done: false}
console.log(gen.next()); // Object {value: undefined, done: true}
  • generator和異步控制:
    利用Generator函數的暫停執行的效果,能夠把異步操做寫在yield語句裏面,等到調用next方法時再日後執行。這實際上等同於不須要寫回調函數了,由於異步操做的後續操做能夠放在yield語句下面,反正要等到調用next方法時再執行。因此,Generator函數的一個重要實際意義就是用來處理異步操做,改寫回調函數。

async和異步:

  • 用法:

    • async 表示這是一個async函數,await只能用在這個函數裏面。

    • await 表示在這裏等待異步操做返回結果,再繼續執行。

    • await 後通常是一個promise對象

  • 示例:async用於定義一個異步函數,該函數返回一個Promise。
    若是async函數返回的是一個同步的值,這個值將被包裝成一個理解resolve的Promise,等同於return Promise.resolve(value)。

await用於一個異步操做以前,表示要「等待」這個異步操做的返回值。await也能夠用於一個同步的值。

let timer = async function timer(){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('500');
        },500);
    });
}
timer().then(result => {
  console.log(result);  //500
}).catch(err => {
    console.log(err.message);
});
//返回一個同步的值
let sayHi = async function sayHi(){
  let hi = await 'hello world';   
  return hi;  //等同於return Promise.resolve(hi);
}
sayHi().then(result => {
  console.log(result);
});

參考:
Promise迷你書
promise筆記
手寫promise
promise實現

相關文章
相關標籤/搜索