<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## Promise 的含義 Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最早提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了`Promise`對象。 所謂`Promise`,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。 `Promise`對象有以下兩個特點。 (1)對象的狀態不受外界影響。`Promise`對象代表一個異步操作,有三種狀態:`pending`(進行中)、`fulfilled`(已成功)和`rejected`(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是`Promise`這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。 (2)一旦狀態改變,就不會再變,任何時候都可以得到這個結果。`Promise`對象的狀態改變,只有兩種可能:從`pending`變為`fulfilled`和從`pending`變為`rejected`。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經發生了,你再對`Promise`對象添加回調函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。 注意,為了行文方便,本章后面的`resolved`統一只指`fulfilled`狀態,不包含`rejected`狀態。 有了`Promise`對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。此外,`Promise`對象提供統一的接口,使得控制異步操作更加容易。 `Promise`也有一些缺點。首先,無法取消`Promise`,一旦新建它就會立即執行,無法中途取消。其次,如果不設置回調函數,`Promise`內部拋出的錯誤,不會反應到外部。第三,當處于`pending`狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。 如果某些事件不斷地反復發生,一般來說,使用[Stream](https://nodejs.org/api/stream.html)模式是比部署`Promise`更好的選擇。 ## 基本用法 ES6 規定,`Promise`對象是一個構造函數,用來生成`Promise`實例。 下面代碼創造了一個`Promise`實例。 ~~~javascript const promise = new Promise(function(resolve, reject) { // ... some code if (/* 異步操作成功 */){ resolve(value); } else { reject(error); } }); ~~~ `Promise`構造函數接受一個函數作為參數,該函數的兩個參數分別是`resolve`和`reject`。它們是兩個函數,由 JavaScript 引擎提供,不用自己部署。 `resolve`函數的作用是,將`Promise`對象的狀態從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出去;`reject`函數的作用是,將`Promise`對象的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并將異步操作報出的錯誤,作為參數傳遞出去。 `Promise`實例生成以后,可以用`then`方法分別指定`resolved`狀態和`rejected`狀態的回調函數。 ~~~javascript promise.then(function(value) { // success }, function(error) { // failure }); ~~~ `then`方法可以接受兩個回調函數作為參數。第一個回調函數是`Promise`對象的狀態變為`resolved`時調用,第二個回調函數是`Promise`對象的狀態變為`rejected`時調用。其中,第二個函數是可選的,不一定要提供。這兩個函數都接受`Promise`對象傳出的值作為參數。 下面是一個`Promise`對象的簡單例子。 ~~~javascript function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100).then((value) => { console.log(value); }); ~~~ 上面代碼中,`timeout`方法返回一個`Promise`實例,表示一段時間以后才會發生的結果。過了指定的時間(`ms`參數)以后,`Promise`實例的狀態變為`resolved`,就會觸發`then`方法綁定的回調函數。 Promise 新建后就會立即執行。 ~~~javascript let promise = new Promise(function(resolve, reject) { console.log('Promise'); resolve(); }); promise.then(function() { console.log('resolved.'); }); console.log('Hi!'); // Promise // Hi! // resolved ~~~ 上面代碼中,Promise 新建后立即執行,所以首先輸出的是`Promise`。然后,`then`方法指定的回調函數,將在當前腳本所有同步任務執行完才會執行,所以`resolved`最后輸出。 下面是異步加載圖片的例子。 ~~~javascript function loadImageAsync(url) { return new Promise(function(resolve, reject) { const image = new Image(); image.onload = function() { resolve(image); }; image.onerror = function() { reject(new Error('Could not load image at ' + url)); }; image.src = url; }); } ~~~ 上面代碼中,使用`Promise`包裝了一個圖片加載的異步操作。如果加載成功,就調用`resolve`方法,否則就調用`reject`方法。 下面是一個用`Promise`對象實現的 Ajax 操作的例子。 ~~~javascript const getJSON = function(url) { const promise = new Promise(function(resolve, reject){ const handler = function() { if (this.readyState !== 4) { return; } if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; const client = new XMLHttpRequest(); client.open("GET", url); client.onreadystatechange = handler; client.responseType = "json"; client.setRequestHeader("Accept", "application/json"); client.send(); }); return promise; }; getJSON("/posts.json").then(function(json) { console.log('Contents: ' + json); }, function(error) { console.error('出錯了', error); }); ~~~ 上面代碼中,`getJSON`是對 XMLHttpRequest 對象的封裝,用于發出一個針對 JSON 數據的 HTTP 請求,并且返回一個`Promise`對象。需要注意的是,在`getJSON`內部,`resolve`函數和`reject`函數調用時,都帶有參數。 如果調用`resolve`函數和`reject`函數時帶有參數,那么它們的參數會被傳遞給回調函數。`reject`函數的參數通常是`Error`對象的實例,表示拋出的錯誤;`resolve`函數的參數除了正常的值以外,還可能是另一個 Promise 實例,比如像下面這樣。 ~~~javascript const p1 = new Promise(function (resolve, reject) { // ... }); const p2 = new Promise(function (resolve, reject) { // ... resolve(p1); }) ~~~ 上面代碼中,`p1`和`p2`都是 Promise 的實例,但是`p2`的`resolve`方法將`p1`作為參數,即一個異步操作的結果是返回另一個異步操作。 注意,這時`p1`的狀態就會傳遞給`p2`,也就是說,`p1`的狀態決定了`p2`的狀態。如果`p1`的狀態是`pending`,那么`p2`的回調函數就會等待`p1`的狀態改變;如果`p1`的狀態已經是`resolved`或者`rejected`,那么`p2`的回調函數將會立刻執行。 ~~~javascript const p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('fail')), 3000) }) const p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000) }) p2 .then(result => console.log(result)) .catch(error => console.log(error)) // Error: fail ~~~ 上面代碼中,`p1`是一個 Promise,3 秒之后變為`rejected`。`p2`的狀態在 1 秒之后改變,`resolve`方法返回的是`p1`。由于`p2`返回的是另一個 Promise,導致`p2`自己的狀態無效了,由`p1`的狀態決定`p2`的狀態。所以,后面的`then`語句都變成針對后者(`p1`)。又過了 2 秒,`p1`變為`rejected`,導致觸發`catch`方法指定的回調函數。 注意,調用`resolve`或`reject`并不會終結 Promise 的參數函數的執行。 ~~~javascript new Promise((resolve, reject) => { resolve(1); console.log(2); }).then(r => { console.log(r); }); // 2 // 1 ~~~ 上面代碼中,調用`resolve(1)`以后,后面的`console.log(2)`還是會執行,并且會首先打印出來。這是因為立即 resolved 的 Promise 是在本輪事件循環的末尾執行,總是晚于本輪循環的同步任務。 一般來說,調用`resolve`或`reject`以后,Promise 的使命就完成了,后繼操作應該放到`then`方法里面,而不應該直接寫在`resolve`或`reject`的后面。所以,最好在它們前面加上`return`語句,這樣就不會有意外。 ~~~javascript new Promise((resolve, reject) => { return resolve(1); // 后面的語句不會執行 console.log(2); }) ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看