搜尋
首頁web前端js教程ES6新功能:JavaScript中內建的延遲物件Promise 程式碼詳細介紹

Promise的基本使用:

利用Promise是解決JS非同步執行時候回呼函數巢狀回呼函數的問題, 更簡潔地控制函數執行流程;

透過new實例化Promise, 建構函數需要兩個參數, 第一個參數為函數執行成功以後執行的函數resolve,第二個函數為函數執行失敗以後執行的函數reject:

new Promise(function(resolve , reject) {
});

透過Promise,我們把回呼函數用線性的方式寫出來,而不是一層套一層, 這個函數有四層回呼;

fn("args", function(a) {
    fn1("foo", function(b) {
        fn2("bar", function(c) {
            fn3("baz", function(d) {
                alert("回调成功,获知的内容为:"+a+b+c+d)
            })
        })
    })
})

以上的Demo只有包含成功的回呼, 如果失敗的回呼也算的話, 也就更麻煩了;

如果使用Promise的方式,我們可以改裝成線性的程式碼,更符合閱讀的習慣,只要在then函數下寫邏輯即可;

new Promise(function(resolve , reject) {
    resolve(1);
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve , reject) {
        resolve(2);
    });
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve , reject) {
        resolve(3);
    });
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve , reject) {
        resolve(4);
    });
}).then(function(val) {
    console.log(val);
});

這是一個ajax異步獲取資料的例子, 我們使用了回呼函數;

<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<script>
    var callback = function(res) {
        console.log(res);
    };
    var ajax = function(url, callback) {
        var r = new XMLHttpRequest();
        r.open("GET", url, true);
        r.onreadystatechange = function () {
            if (r.readyState != 4 || r.status != 200) return;
            var data = JSON.parse(r.responseText);
            callback(data);
        };
        r.send();
    };
    //执行请求:
    ajax("http://www.filltext.com?rows=10&f={firstName}", callback);
    //再做别的事情;
</script>
</body>
</html>

因為ES6內建了Promise, 我們可以把以上的callback改寫成promise的方式, 首先ajax函數回傳一個Promise物件;

<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
        var callback = function(res) {
            console.log(res);
        };
        var ajax = function(url) {
            return new Promise(function(resolve, reject) {
                var r = new XMLHttpRequest();
                r.open("GET", url, true);
                r.onreadystatechange = function () {
                    if (r.readyState != 4 || r.status != 200) return;
                    var data = JSON.parse(r.responseText);
                    resolve(data);
                };
                r.send();
            })
        };
        //执行请求:
        ajax("http://www.filltext.com?rows=10&f={firstName}").then(function(data) {
            callback(data);
        });
        //再做别的事情;
    </script>
</body>
</html>

Promise實例的三種狀態:

每一個實例化的Promise都有三個狀態;pending(等待)  rejected(拒絕)  resolved(解決) ,預設的狀態為pending,如果執行了resolve(), 那麼這個promise的狀態會變為resolve,如果執行了reject(), 那麼這個promise的狀態就會變成rejected, 而且這些狀態是不可撤銷的,一經更改,不會再變了;

then方法:

promise有一個then方法,then方法接收兩個參數, 第一個為函數的成功回調, 第二個為函數的失敗回呼:

var promise = new Promise(function(resolve , reject) {
    resolve(); //执行成功回调;
});
console.log(0);
promise.then(function(val) {
    console.log(1); 
}, function() {
    console.log("失败");
});
console.log("2");
var promise = new Promise(function(resolve , reject) {
    reject();
});
console.log(0);
promise.then(function(val) {
    console.log(1);
}, function() {
    console.log("失败");
});
console.log("2");

then方法每一次都是傳回不同的Promise實例,then的第一個參數是成功回調, 這個成功回呼的參數為: 上一個Promise實例執行resolve方法的參數;

一般來說, then方法會傳回目前的 promise , 如果在then方法裡面return 一個新的Promise實例,那麼此時的then返回的就是新的Promise實例, 利用這個特性,就可以實現多層回調;

new Promise(function(resolve , reject) {
    resolve(1);
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve , reject) {
        resolve(2);
    });
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve , reject) {
        resolve(3);
    });
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve , reject) {
        resolve(4);
    });
}).then(function(val) {
    console.log(val);
});

不管程式碼是異步還是同步的, 都可以用Promise的then方法, 同步的程式碼直接寫在then方法第一個參數, 把需要參數透過resolve傳給下一個then方法,

#如果是異步的程式碼,就直接return一個Promise實例:

new Promise(function(resolve , reject) {
    resolve(1);
}).then(function(val) {
    console.log(val);
    return 2;
}).then(function(val) {
    console.log(val);
    return 3;
}).then(function(val) {
    console.log(val);
    return new Promise(function(resolve,reject) {
        //异步操作些这里
        resolve(4);
    });
}).then(function(val) {
    console.log(val);
    return 5;
}).then(function(val) {
    console.log(val);
});

catch方法:

catch方法和失敗回呼時一樣的, 如果上一個非同步函數 拋出了錯誤了,錯誤會被捕獲, 並執行 catch方法或失敗回呼;

var promise = new Promise(function(resolve , reject) {
    resolve(); //执行成功回调;
});
console.log(0);
promise.then(function(val) {
    console.log("成功");
    throw new Error("heheda");
}).catch(function(e) {
    console.log(e);
}).then(function() {
    console.log("继续执行");
});

Promise中的錯誤是會一層層傳遞的, 如果錯誤沒有沒有被捕獲, 會一直傳遞給下一個promise對象, 直到被捕獲為止, 然後繼續往下執行:

new Promise(function(resolve , reject) {
    resolve(1);
}).then(function(val) {
        console.log(val);
        return new Promise(function(resolve , reject) {
            throw new Error("err");
        });
    }).then(function(val) {
        console.log(val);
        return new Promise(function(resolve , reject) {
            resolve(3);
        });
    }).then(function(val) {
        console.log(val);
        return new Promise(function(resolve , reject) {
            resolve(4);
        });
    }).then(function(val) {
        console.log(val);
    }).catch(function(err) {
        console.log(err);
    }).then(function() {
        console.log("继续执行")
    })

建構子Promise的四個方法:

建構子Promise有四個方法, Promise .all, Promise.race, Promise.reject, Promise.resolve:

Promise.all(iterable)
返回一個promise對象,當iterable參數裡所有的promise都被解決後,該promise也會被解決

要注意all方法是Promise函數的方法,不是實例的方法,參數是數組, 數組裡面全是Promise的實例 :

var p0 = new Promise(function(resolve) {
    setTimeout(function() {
        resolve(0)
    },1000);
})
var p1 = new Promise(function(resolve) {
    setTimeout(function() {
        resolve(1)
    },2000);
})
var p2 = new Promise(function(resolve) {
    setTimeout(function() {
        resolve(2)
    },3000);
})
Promise.all([p0,p1,p2]).then(function(arr) {
    console.log(arr)
})

Promise.race(iterable)

當iterable參數裡的任一個子promise被成功或失敗後,父promise馬上也會以子promise的成功傳回值或失敗詳情作為參數呼叫父promise綁定的對應句柄,並傳回該promise物件。

Promise.reject(reason)

#呼叫Promise的rejected句柄,並傳回這個Promise物件。

Promise.resolve(value)

#用成功值value解決一個Promise物件。如果該value為可繼續的(thenable,即帶有then方法),則傳回的Promise物件會「跟隨」這個value,採用這個value的最終狀態;否則的話傳回值會用這個value滿足(fullfil)傳回的Promise對象。

官方的範例:

<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<p id="log"></p>
<script>
    &#39;use strict&#39;;
    var promiseCount = 0;
    function testPromise() {
        var thisPromiseCount = ++promiseCount;

        var log = document.getElementById(&#39;log&#39;);
        log.insertAdjacentHTML(&#39;beforeend&#39;, thisPromiseCount + &#39;) 开始(同步代码开始)<br/>&#39;);

        // 我们创建一个新的promise: 然后用&#39;result&#39;字符串解决这个promise (3秒后)
        var p1 = new Promise(function (resolve, reject) {
            // 解决函数带着解决(resolve)或拒绝(reject)promise的能力被执行
            log.insertAdjacentHTML(&#39;beforeend&#39;, thisPromiseCount + &#39;) Promise开始(异步代码开始)<br/>&#39;);

            // 这只是个创建异步解决的示例
            window.setTimeout(function () {
                // 我们满足(fullfil)了这个promise!
                resolve(thisPromiseCount)
            }, Math.random() * 2000 + 1000);
        });

        // 定义当promise被满足时应做什么
        p1.then(function (val) {
            // 输出一段信息和一个值
            log.insertAdjacentHTML(&#39;beforeend&#39;, val + &#39;) Promise被满足了(异步代码结束)<br/>&#39;);
        });

        log.insertAdjacentHTML(&#39;beforeend&#39;, thisPromiseCount + &#39;) 建立了Promise(同步代码结束)<br/><br/>&#39;);
    }
    testPromise();
</script>
</body>
</html>

既然有了Promise , 我們就可以把封裝XMLHttpRequest封裝成GET方法,方便使用:

function get(url) {
  // Return a new promise.
  return new Promise(function(resolve, reject) {
    // Do the usual XHR stuff
    var req = new XMLHttpRequest();
    req.open(&#39;GET&#39;, url);

    req.onload = function() {
      // This is called even on 404 etc
      // so check the status
      if (req.status == 200) {
        // Resolve the promise with the response text
        resolve(req.response);
      }
      else {
        // Otherwise reject with the status text
        // which will hopefully be a meaningful error
        reject(Error(req.statusText));
      }
    };

    // Handle network errors
    req.onerror = function() {
      reject(Error("Network Error"));
    };

    // Make the request
    req.send();
  });
}

然後使用:

get(&#39;story.json&#39;).then(function(response) {
  console.log("Success!", response);
}, function(error) {
  console.error("Failed!", error);
});

假資料的位址可以自己設置, 可以透過控制台請求, 注意跨域的問題;

封裝XMLHttpRequest成Promise非同步載入圖片的案例:http: //www.php.cn/

其他:

以上只是Promise的一些基礎知識, 還有一些其他的知識點, 因為能力有限不一一介紹了(Promise.resolve的不同參數, 與Generator一起使用, Promise的附加方法, 等等等等);

把Promise的運行流程畫出來, 對Promise的理解會好一點, Promise還是比較繞的

瀏覽器支援情況:

#

Chrome 32, Opera 1,Firefox 29, Safari 8 ,Microsoft Edge, 這些瀏覽器以上都預設支援;

 以上就是ES6新功能:JavaScript中內建的延遲物件Promise 程式碼詳細介紹的內容,更多相關內容請關注PHP中文網(www.php.cn)!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

幕後:什麼語言能力JavaScript?幕後:什麼語言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

JavaScript是用C編寫的嗎?檢查證據JavaScript是用C編寫的嗎?檢查證據Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript的角色:使網絡交互和動態JavaScript的角色:使網絡交互和動態Apr 24, 2025 am 12:12 AM

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版