天天看點

ES6——Promise函數一、三個狀态二、基本用法三、then()四、Promise.all()五、Promise.race()六、Promise.resolve()七、Promise.reject()八、Generator 函數與 Promise 的結合

文章目錄

  • 一、三個狀态
  • 二、基本用法
    • 1.舉例
    • 2.使用原生Ajax
    • 3.圖檔異步加載(懶加載)
  • 三、then()
  • 四、Promise.all()
  • 五、Promise.race()
  • 六、Promise.resolve()
  • 七、Promise.reject()
  • 八、Generator 函數與 Promise 的結合

異步程式設計解決方案

一、三個狀态

1.promise内部狀态 不受外界影響,由異步程式設計結果決定

pending進行中

fulfilled成功

rejected失敗

2.promise中的狀态 一旦發生變化不會再修改

Promise對象的狀态改變,隻有兩種可能:

從pending變為fulfilled 和 從pending變為rejected

二、基本用法

ES6 規定,Promise對象是一個構造函數,用來生成Promise執行個體

Promise構造函數接受一個函數作為參數,該函數的兩個參數分别是resolve和reject,它們是兩個函數

resolve函數的作用是,将Promise對象的狀态從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并将異步操作的結果,作為參數傳遞出去;

reject函數的作用是,将Promise對象的狀态從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并将異步操作報出的錯誤,作為參數傳遞出去

1.舉例

let promise=new Promise((resolve,reject)=>{
        let status=true;
        if(status){
            resolve('成功');
        }
        else{
            reject(new Error('失敗'));
        }
    })

    //promise對象的使用
    //寫法一
    promise.then((res)=>{
        //成功回調函數 resolve
        console.log(res);
    },(error)=>{
        console.log(error);
    })
    //輸出:   成功

	//寫法二
	    promise.then((res)=>{
        //resolve
        console.log(res);
    }).catch(()=>{
        //reject
        console.log(error);
    }).finally(()=>{
        console.log("最終執行的代碼");
    });
    //輸出:  成功 最終執行的代碼
           

2.使用原生Ajax

function Ajax(method,url,data,callback){
        var http;
        if(window.XMLHttpRequest){
            http=new XMLHttpRequest();
        }
        else{
            //IE5,IE6
            http=new ActiveXObject("Microsoft.XMLHTTP");
        }
        if(method=="get"){
            if(data){
                url+="?";
                url+=data;
            }
            http.open(method,url);
            http.send();
        }
        else{
            http.open(method,url);
            if(data){
                http.send(data);
            }
            else{
                http.send();
            }
        }
        http.onreadystatechange= function () {
            if(http.readyState==4&&http.status==200){
                //匿名函數回調 才能把資料拿到外面使用
                callback(http.response);
            }
        }
    }
    
    let promise=new Promise((resolve,reject)=>{
        try{
            Ajax('get','./city.json',null,(res)=>{
                resolve(res);
            });
        }
        catch(e){
            reject(e);
        }
    })

    promise.then((res)=>{
     //resolve
     	console.log(res);
     }).catch(()=>{
     //reject
     	console.log(error);
     }).finally(()=>{
     	console.log("最終執行的代碼");
     });
           
ES6——Promise函數一、三個狀态二、基本用法三、then()四、Promise.all()五、Promise.race()六、Promise.resolve()七、Promise.reject()八、Generator 函數與 Promise 的結合

(上面内容即為city.json的全部内容)

3.圖檔異步加載(懶加載)

異步加載要比同步加載快很多

let promise= function (src) {
        return new Promise(function (resolve,reject) {
            let image=new Image();
            image.onload= function () {
                resolve(this); //即image
            }
            image.onerror= function () {
                reject(new Error("圖檔加載失敗"));
            }
            image.src=src;   //相當于給浏覽器緩存了一張圖檔
        })
    }
    
    let src='./1.jpg'
    promise(src).then((img)=>{
        console.log(img);
        document.body.appendChild(img);
    }).catch((error)=>{
        console.log(error);
    })
           
ES6——Promise函數一、三個狀态二、基本用法三、then()四、Promise.all()五、Promise.race()六、Promise.resolve()七、Promise.reject()八、Generator 函數與 Promise 的結合

三、then()

1.then方法定義在原型對象Promise.prototype上

ES6——Promise函數一、三個狀态二、基本用法三、then()四、Promise.all()五、Promise.race()六、Promise.resolve()七、Promise.reject()八、Generator 函數與 Promise 的結合

2.then方法傳回的是一個新的Promise執行個體(注意,不是原來那個Promise執行個體)。

是以可以采用鍊式寫法,即then方法後面再調用另一個then方法。

let promise=new Promise(function (resolve,reject) {
        let data={
            json: function () {
                return {id:1};
            }
        }
        if(data){
            resolve(data);
        }
        else{
            reject(new Error("出錯了"));
        }
    })
    promise.then(function (res) {
//        console.log(res);  //{json: ƒ}
        return res.json();
    }).then(function (res) {
        console.log(res);  //{id: 1}
    })
           

四、Promise.all()

将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體

(1)隻有p1、p2、p3的狀态都變成fulfilled,p的狀态才會變成fulfilled,此時p1、p2、p3的傳回值組成一個數組,傳遞給p的回調函數。

(2)隻要p1、p2、p3之中有一個被rejected,p的狀态就變成rejected,此時第一個被reject的執行個體的傳回值,會傳遞給p的回調函數。

let p1=new Promise((resolve,rejecr)=>{
        resolve(1);
    });
    let p2=new Promise((resolve,rejecr)=>{
        resolve(2);
    })
    let p=Promise.all([p1,p2]);
    p.then((result)=>{
        console.log(result);   // [1, 2]
    })
           
let p1=new Promise((resolve,rejecr)=>{
        resolve(1);
    });
    let p2=new Promise((resolve,rejecr)=>{
        reject(new Error("失敗"));
    })
    let p=Promise.all([p1,p2]);
    p.then((result)=>{
        console.log(result); 
    }).catch((err)=>{
        console.log(err);  //Error: 失敗
    })
           

五、Promise.race()

同樣是将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體

隻要p1、p2、p3之中有一個執行個體率先改變狀态,p的狀态就跟着改變。

那個率先改變的 Promise 執行個體的傳回值,就傳遞給p的回調函數

let p1=new Promise((resolve,reject)=>{
        //模拟請求 5000ms請求回來的資料
        setTimeout(function () {
            resolve("資料");
        },5000);
    });
    let p2=new Promise((resolve,reject)=>{
        //模拟請求 2s後按逾時處理
        setTimeout(function () {
            reject(new Error("逾時"));
        },2000);
    });
    let p=Promise.race([p1,p2]);
    p.then((res)=>{
        console.log(res);
    }).catch((err)=>{
        console.log(err);
    });
           

兩秒後,p2狀态先改變:

ES6——Promise函數一、三個狀态二、基本用法三、then()四、Promise.all()五、Promise.race()六、Promise.resolve()七、Promise.reject()八、Generator 函數與 Promise 的結合

六、Promise.resolve()

将現有對象轉為一個新的 Promise 對象

Promise.resolve(12);
    //等價
    new Promise(resolve=>resolve(12));
           

(1)如果參數是 Promise 執行個體,那麼Promise.resolve将不做任何修改、原封不動地傳回這個執行個體。

(2)參數是一個thenable對象(即如果轉化對象存在then方法)

會預設執行自身的then方法

let obj={
        then: function (resolve) {
            resolve(22);
        }
    }
    let p=Promise.resolve(obj);
    p.then(function (res) {
        console.log(res); //22
    })
           

(3)不是thenable對象

let obj={id:1};
    let p=Promise.resolve(obj);
    p.then(function (res) {
        console.log(res);  //{id: 1}
    })
           

七、Promise.reject()

也會傳回一個新的 Promise 執行個體,該執行個體的狀态為rejected

Promise.reject(new Error("失敗"));
//等價
new Promise((resolve,reject)=>reject(new Error("失敗")))
           

八、Generator 函數與 Promise 的結合

使用 Generator 函數管理流程,遇到異步操作的時候,通常傳回一個Promise對象

let p= function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                resolve("資料");
            },3000)
        })
    }
    let gen= function* (){
        try{
            let res=yield p();
            console.log(res);
        }catch(e){
            throw e.message;
        }
    }
    function run(Generator){
        let it=Generator(); //傳回周遊器

        function go(result){
            if(result.done){
                return result.value;
            }
            return result.value.then(function (res) {
            	//console.log(res);  //資料
                return go(it.next(res));
            }).catch(function (err) {
                it.throw(err);
            })
        }
        go(it.next());
    }
    run(gen);
    //三秒後輸出: 資料
           
es6