JavaScript Promise(基礎)

一、Promise是什麼?

  • promsie是ES6新增的一個特性,它已經列入ES6的正式規範中
  • promise是抽象處理對象以及對其進行各類操做的組件,是一種異步流程的控制手段。
  • javaScript和Node都是單線程非阻塞的,因此就會有異步回調的問題,promise就是爲了解決這類問題的。
  • Promise能夠支持多個併發的請求,獲取併發請求中的數據。
  • Promise可使用鏈式調用的方法來組織代碼,因此使用Promise對象後,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套讓代碼更加的直觀。
示例:
$.ajax(url1, function(data1){
    // do something...
    $.ajax(url2, function(data2){
        // do something...
        $.ajax(url3, function(data3){
            // do something...
            done(data3); // 返回數據
        });
    });
});
複製代碼

未使用promise,回調必須層層嵌套(回調地獄),代碼難以維護,第一的輸出是第二個的輸入時,須要等待上一個操做完成才能夠進行下一個操做,形成沒必要要的等待。javascript


二、Promise的狀態

2.1 Promise對象有三種狀態
  • Pending(等待態)
    • 既不是resolve也不是reject的狀態,也就是promise對象剛建立後的初始化狀態;
  • Resolved/Fulfilled(成功態)
    • resolve(成功)時,此時會調用onFuifilled;
  • Rejected(失敗態)
    • reject(失敗)時,此時會調用onRejected;

promise只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。java

2.2 狀態一旦改變就不會再變,任什麼時候候均可以獲得這個結果。
  • 若是一旦promise成功了就不能失敗,相反也是同樣的,只有狀態是等待的狀態時才能夠轉化狀態
    • promise對象的狀態改變,只有兩種可能:從Pending變爲Resolved和從Pending變爲Rejected

pending->fulfilledpending->rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果.ajax

2.3 Promise的缺點
  • 沒法取消,一旦新建就會當即執行,沒法中途取消。
  • 若是不設置回調函數,promise內部拋出的錯誤,不會反應到外部。
  • 當處於pending狀態時,沒法肯定進展到哪一階段,剛開始仍是即將完成。

三、Promise的使用

3.1基本用法
  • 首先要new一個Promise,將Promise實例化
  • 實例化的promise能夠傳兩個參數,一個是成功以後的resolve,一個是失敗以後的reject
    • Promise本省只有一個參數,叫executor(執行器),默認new時就會調用
  • 每個Promise的實例上都有一個then方法(異步的),能夠用then方法分別指定Resolved狀態和Reject狀態的回調函數

代碼示例: 默認promise中的executor默認執行數組

let p=new Promise((resolve,reject)=>{
    console.log(1);
});
console.log(2);
複製代碼

執行順序

代碼示例: 調用onFuifilledpromise

let p=new Promise((resolve,reject)=>{
  resolve('成功');
});

p.then((value)=>{//value成功的緣由
  console.log(value);
},(err)=>{//err失敗的緣由
  console.log(err);
})
複製代碼

成功

代碼示例: 調用onRejected併發

let p=new Promise((resolve,reject)=>{
  reject('失敗');
});

p.then((value)=>{//value成功的緣由
  console.log(value);
},(err)=>{//err失敗的緣由
  console.log(err);
})
複製代碼

失敗

代碼示例: 成功了就不能失敗,相反也同樣異步

let p=new Promise((resolve,reject)=>{//
  resolve('成功');
  reject('失敗');
});

p.then((value)=>{//value成功的緣由
  console.log(value);
},(err)=>{//err失敗的緣由
  console.log(err);
})
複製代碼

成功就不能失敗

代碼示例: 成功了就不能失敗,相反也同樣函數

let p=new Promise((resolve,reject)=>{
    throw new Error('發生錯誤');
});
p.then((value)=>{//value成功的緣由
	console.log(value);
},(err)=>{//err失敗的緣由
	console.log(err);
})
複製代碼

發生錯誤

3.2鏈式操做
  • 經過維護狀態、傳遞狀態的方式來使回調可以及時的調用,上一個操做完成以後才能夠進行下一個操做,相比callback更靈活簡單
  • promise實現鏈式調用返回的並非this,而是一個新的promise

代碼示例:ui

Promise1().then((value)=>{
  console.log(valuse);
  return Promise2();
}).then((value)=>{
  console.log(value);
  return Promise3();
}).then((value)=>{
  console.log(value);
})//能夠then到天荒地老

function Promise1(){
  return new Promsie((resolve,reject)=>{
    setTimeout(function(){//異步操做
      console.log('異步1');
      resolve('異步1傳的值');
    },1000);
  })
}
function Promise2(){
  return new Promsie((resolve,reject)=>{
    setTimeout(function(){//異步操做
      console.log('異步2');
      resolve('異步2傳的值');
    },3000);
  })
}
function Promise3(){
  return new Promsie((resolve,reject)=>{
    setTimeout(function(){//異步操做
      console.log('異步3');
      resolve('異步3傳的值');
    },2000);
  })
}
複製代碼

輸出的值爲: 異步1 異步1傳的值 異步2 異步2傳的值 異步3 異步3傳的值this

3.2 Promise的catch方法
  • catch方法是then(onFulfilled,onRejected)方法中onRejected函數的簡單寫法,也就是能夠寫成then(fn).catch(fn),至關於then(fn).then(null,fn);

代碼示例:

let p=((isReady)=>{
  return new Promise(()=>{
    if(isready){
      return resolve('hello');
    }else{
      return reject('failure');
    }
  });
})

p(true).then((value)=>{
    console.log('resolved');
    console.log(value);
    console.log(aa); 
  }).catch((err)=>{
    console.log('rejected');
    console.log(err);
  });
複製代碼

輸出的值爲: resolved hell rejected ReferenceError: aa is not defined...

3.3 promise.all方法
  • promise.all接收一個爲promise對象的數組做爲參數,當這個數組裏全部的promise對象都變爲resolve時,該方法纔會返回。

代碼示例:

let p1=new Promise((resolve,reject)=>{
  setTimeout(function(){
    resolve('Promise1');
  },1000);
})
let p2=new Promise((resolve,reject)=>{
  setTimeout(function(){
    resolve('Promise2');
  },3000);
})

Promise.all([p1,p2]).then((result)=>{
  console.log(result);
})
複製代碼

輸出結果 ['Promise1','Promise2']

3.4 promise.race方法
  • race的意思賽跑,也就是看誰跑的快,跑的快的就贏了。所以,promise.race也是傳入一個數組,可是與promise.all不一樣的是,promise.race只返回跑的快的值。

代碼實例:

let p1=new Promise((resolve,reject)=>{
    setTimeout(function(){
      console.log(1);
      resolve('Promise');
    },3000);
  })
  let p2=new Promise((resolve,reject)=>{
    console.log(2);
    resolve('Promise2');
  },1000)

  Promise.race([p1,p2]).then((result)=>{
    console.log(result);
  })
複製代碼

輸出結果: 2 Promised 1

  • 能夠看到傳的值中,只有p2的返回了,但p1沒有中止,依然執行。

Promise的基礎就到這裏了,若是您以爲文章有用請點贊!!!

相關文章
相關標籤/搜索