aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/javascript/reference/global_objects/promise/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/zh-tw/web/javascript/reference/global_objects/promise/index.html')
-rw-r--r--files/zh-tw/web/javascript/reference/global_objects/promise/index.html256
1 files changed, 256 insertions, 0 deletions
diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/index.html
new file mode 100644
index 0000000000..8ec1456ae1
--- /dev/null
+++ b/files/zh-tw/web/javascript/reference/global_objects/promise/index.html
@@ -0,0 +1,256 @@
+---
+title: Promise
+slug: Web/JavaScript/Reference/Global_Objects/Promise
+translation_of: Web/JavaScript/Reference/Global_Objects/Promise
+---
+<div>{{JSRef}}</div>
+
+<p><strong><code>Promise</code></strong> 物件代表一個即將完成、或失敗的非同步操作,以及它所產生的值。</p>
+
+<div class="note">
+<p>此條目為介紹 Promise 建構式。要瞭解 Promise 相關使用方式,請先參考<a href="/zh-TW/docs/Web/JavaScript/Guide/Using_promises">使用 Promise</a>。Promise 建構式主要用於包裹尚未支援 Promise 的函式。</p>
+</div>
+
+<div>{{EmbedInteractiveExample("pages/js/promise-constructor.html")}}</div>
+
+
+
+<p class="hidden">The source for this interactive demo is stored in a GitHub repository. If you'd like to contribute to the interactive demo project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>
+
+<h2 id="語法">語法</h2>
+
+<pre class="brush: js">new Promise( /* executor */ function(resolve, reject) { ... } );</pre>
+
+<h3 id="參數">參數</h3>
+
+<dl>
+ <dt>executor</dt>
+ <dd>為一個依序接收兩個參數的函式:<code>resolve</code> 及 <code>reject</code>(實現及拒絕回呼函式)。在 Promise 實作中,<code>executor</code> 函式在傳入參數 <code>resolve</code> 與 <code>reject</code> 後會立刻執行(<code>executor</code> 函式會在 <code>Promise</code> 建構式回傳 Promise 物件前被執行)。<code>resolve</code> 與 <code>reject</code> 函式,會在被個別呼叫時,個別執行之。通常 executor 函式會發起一些非同步操作。接著,成功完成後執行 <code>resolve</code> 以完成 promise;或如果有錯誤,執行 <code>rejects</code>。<br>如果 executor 函式在執行中拋出錯誤,promise 會被拒絕(rejected),回傳值也將被忽略。</dd>
+</dl>
+
+<h2 id="描述">描述</h2>
+
+<p><code><strong>Promise</strong></code> 會代理一個建立時,不用預先得知的值。它使你能夠繫結(associate)著發動非同步操作後,最終的成功值(success value)或失敗訊息(failure reason)的處理函式(handlers)。這讓非同步方法回傳值的方式很像同步方法,但不是回傳最終結果:非同步方法回傳一個 <em>promise</em> 物件作為未來某時間點的值。</p>
+
+<p>一個 <code>Promise</code> 物件處於以下幾種狀態:</p>
+
+<ul>
+ <li><em>擱置(pending)</em>:初始狀態,不是 fulfilled 與 rejected。</li>
+ <li><em>實現(fulfilled)</em>:表示操作成功地完成。</li>
+ <li><em>拒絕(rejected)</em>:表示操作失敗了。</li>
+</ul>
+
+<p>一個處於擱置狀態的 promise 能以一個值被實現(fulfilled),或是以一個原因或錯誤而被拒絕(rejected)。當上述任一狀態轉換發生時,那些透過 <code>then</code> 方法所繫結(associated)的處理函式列隊就會依序被調用。(若一個 promise 已被實現或拒絕,繫結(attached)於它的處理函式將立即被呼叫,因此完成非同步操作與繫結處理函式之間不存在競爭條件(race condition)。)</p>
+
+<p>由於 <code>{{jsxref("Promise.then", "Promise.prototype.then()")}}</code> 以及 <code>{{jsxref("Promise.catch", "Promise.prototype.catch()")}}</code> 方法都回傳 promise,它們可以被串接。</p>
+
+<p><img alt="" src="https://cdn.rawgit.com/Vectaio/a76330b025baf9bcdf07cb46e5a9ef9e/raw/26c4213a93dee1c39611dcd0ec12625811b20a26/js-promise.svg"></p>
+
+<div class="note">
+<p><strong>容易混淆:</strong> 許多其他語言擁有機制用來惰性求值(lazy evaluation)及延遲(deferring)運算,它們也被稱作“promises” — e.g. Scheme. 然而在 JavaScript 中 Promises 代表那些(已經)發生中(happening)的程序,它們可以繫結回呼函式。若您要找的是惰性求值表示式,考慮不帶參數的 <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">arrow function</a>:<code>f = () =&gt; <em>expression</em></code> 來建立惰性求值表示式,並透過 <code>f()</code> 進行求值.</p>
+</div>
+
+<div class="note">
+<p><strong>Note</strong>: 一個被實現或拒絕,但不處於 pending 的 promise 被稱作被解決(settled)。您也會見到使用解決(resolved)一詞來描述 promises — 這代表 promises 被實現(fulfilled)了。<a href="https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md">States and fates</a> 這篇文章包含了更多 promises 的專有名詞。</p>
+</div>
+
+<h2 id="屬性">屬性</h2>
+
+<dl>
+ <dt><code>Promise.length</code></dt>
+ <dd>長度屬性,值固定為 <code>1</code>。(建構式參數數目).</dd>
+ <dt>{{jsxref("Promise.prototype")}}</dt>
+ <dd><code>Promise</code> 建構式的原型(prototype).</dd>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{jsxref("Promise.all", "Promise.all(iterable)")}}</dt>
+ <dd>回傳一個 promise,當在引數 iterable 中所有 promises 都被實現時被實現,或在引數 iterable 中有一個 promise 被拒絕時立刻被拒絕。若回傳的 promise 被實現,它將以一個實現值的陣列被實現,其順序與 iterable 中的 promises 相同。若回傳的 promise 被拒絕,它將以失敗訊息被拒絕,此訊息來自第一個在 iterable 中被拒絕的 promise。這個方法在聚集許多 promises 的結果時很有效。</dd>
+ <dt>{{jsxref("Promise.race", "Promise.race(iterable)")}}</dt>
+ <dd>回傳一個被實現或拒絕的 promise,當 iterable 中有一個 promise 被實現或拒絕時。</dd>
+</dl>
+
+<dl>
+ <dt>{{jsxref("Promise.reject", "Promise.reject(reason)")}}</dt>
+ <dd>回傳一個以失敗訊息拒絕的 <code>promise</code>。</dd>
+</dl>
+
+<dl>
+ <dt>{{jsxref("Promise.resolve", "Promise.resolve(value)")}}</dt>
+ <dd>回傳一個以 value 實現的 <code>promise</code>。若該值為 thenable (i.e. 具有 <code>then</code> 方法),回傳的 promise 將跟隨(follow)之,採用她的最終狀態; 在其他情形回傳的 promise 將以 value 被實現。一般來說,當您不知道 value 是否為 promise,使用 {{jsxref("Promise.resolve", "Promise.resolve(value)")}},將回傳值以 promise 作處理。</dd>
+</dl>
+
+<h2 id="Promise_原型"><code>Promise</code> 原型</h2>
+
+<h3 id="屬性_2">屬性</h3>
+
+<p>{{page('zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/prototype','屬性')}}</p>
+
+<h3 id="方法_2">方法</h3>
+
+<p>{{page('zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/prototype','方法')}}</p>
+
+<h2 id="建立_Promise">建立 Promise</h2>
+
+<p><code><font face="Open Sans, arial, x-locale-body, sans-serif">一個</font></code> <code>Promise</code> 物件透過 <code>new</code> 及其建構式建立。這個建構式接收一個叫作”執行器函式(executor function)“的引數。此函式接收兩個函式作為引數。第一個函式(<code>resolve)</code>在非同步作業成功完成時,以該作業之結果值被呼叫。第二個函式(<code>reject</code>)在作業失敗時,以失敗訊息,通常是一個 error object,被呼叫。</p>
+
+<pre class="brush: js">const myFirstPromise = new Promise((resolve, reject) =&gt; {
+ // 執行一些非同步作業,最終呼叫:
+ //
+ // resolve(someValue); // 實現
+ // 或
+ // reject("failure reason"); // 拒絕
+});
+</pre>
+
+<p>要提供一個函式 promise 功能,讓它回傳一個 promise 即可:</p>
+
+<pre class="brush: js">function myAsyncFunction(url) {
+ return new Promise((resolve, reject) =&gt; {
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.onload = () =&gt; resolve(xhr.responseText);
+ xhr.onerror = () =&gt; reject(xhr.statusText);
+ xhr.send();
+ });
+};</pre>
+
+<h2 id="範例">範例</h2>
+
+<h3 id="入門範例">入門範例</h3>
+
+<pre class="brush: js">let myFirstPromise = new Promise((resolve, reject) =&gt; {
+ // 當非同步作業成功時,呼叫 resolve(...),而失敗時則呼叫 reject(...)。
+ // 在這個例子中,使用 setTimeout(...) 來模擬非同步程式碼。
+ // 在實務中,您將可能使用像是 XHR 或者一個 HTML5 API.
+ setTimeout(function(){
+ resolve("Success!"); // Yay!非常順利!
+ }, 250);
+});
+
+myFirstPromise.then((successMessage) =&gt; {
+ // successMessage 是任何您由上方 resolve(...) 傳入的東西。
+ // 在此僅作為成功訊息,但是它不一定是字串。
+ console.log("Yay! " + successMessage);
+});
+</pre>
+
+<h3 id="進階範例">進階範例</h3>
+
+<pre class="brush: html hidden">&lt;button id="btn"&gt;Make a promise!&lt;/button&gt;
+&lt;div id="log"&gt;&lt;/div&gt;
+</pre>
+
+<p><code>這個小範例演示了</code> <code>Promise</code> <code>的運作機制。每當 </code>{{HTMLElement("button")}} 被點擊時,<code>testPromise()</code> 方法被呼叫。每次點擊將透過 {{domxref("window.setTimeout()")}} 建立一個將在 1-3 秒內隨機地被實現的 promise,供 promise 計數(一個從 1 開始的數值)。建構式 <code>Promise()</code> 被用來建立 promise。</p>
+
+<p>promise 的實現值單純地經由一個實現回呼函式 {{jsxref("Promise.prototype.then()","p1.then()")}} 被印出。下以一些文字紀錄來展現方法中同步的與非同步處理 promise 的部分是如何分離彼此。</p>
+
+<pre class="brush: js">'use strict';
+var promiseCount = 0;
+
+function testPromise() {
+ let thisPromiseCount = ++promiseCount;
+
+ let log = document.getElementById('log');
+ log.insertAdjacentHTML('beforeend', thisPromiseCount +
+ ') Started (&lt;small&gt;Sync code started&lt;/small&gt;)&lt;br/&gt;');
+
+ // 建立一個新的 promise:此 promise 承諾一個數值計數, 由 1 開始(等待約 2 秒)
+ let p1 = new Promise(
+ // 這個解決器函數(resolver function)呼叫實現或
+ // 拒絕 promise。
+ (resolve, reject) =&gt; {
+ log.insertAdjacentHTML('beforeend', thisPromiseCount +
+ ') Promise started (&lt;small&gt;Async code started&lt;/small&gt;)&lt;br/&gt;');
+ // 在此例子單純用來產生非同步特性。
+ window.setTimeout(
+ function() {
+ // 實現這個 promise!
+ resolve(thisPromiseCount);
+ }, Math.random() * 2000 + 1000);
+ }
+ );
+
+ // 接著透過呼叫 then() 來決定 promise 進入 resolved 時,要透過 then() 做什麼,
+ // 或是進入 rejected 時,要透過 catch() 方法要做什麼。
+ p1.then(
+ // 印出實現值(fulfillment value)
+ function(val) {
+ log.insertAdjacentHTML('beforeend', val +
+ ') Promise fulfilled (&lt;small&gt;Async code terminated&lt;/small&gt;)&lt;br/&gt;');
+ })
+ .catch(
+ // 印出失敗訊息(rejection reason)
+ (reason) =&gt; {
+ console.log('Handle rejected promise ('+reason+') here.');
+ });
+
+ log.insertAdjacentHTML('beforeend', thisPromiseCount +
+ ') Promise made (&lt;small&gt;Sync code terminated&lt;/small&gt;)&lt;br/&gt;');
+}</pre>
+
+<p><sub>*譯註:resolver function 即 executor function。</sub></p>
+
+<pre class="brush:js hidden">if ("Promise" in window) {
+ let btn = document.getElementById("btn");
+ btn.addEventListener("click",testPromise);
+} else {
+ log = document.getElementById('log');
+ log.innerHTML = "Live example not available as your browser doesn't support the &lt;code&gt;Promise&lt;code&gt; interface.";
+}
+</pre>
+
+<p>這個範例從點擊按鈕開始。您的瀏覽器需要支援 Promise。在短時間內點擊按鈕許多次,您甚至將看到不同的 promises 一個接一個地被實現。</p>
+
+<p>{{EmbedLiveSample("Advanced_Example", "500", "200")}}</p>
+
+<h2 id="使用_XHR_載入圖片">使用 XHR 載入圖片</h2>
+
+<p>另一個使用 <code>Promise</code> and <code><a href="/zh-TW/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a></code> 來載入圖片的簡單例子可以在 MDN GitHub <a href="https://github.com/mdn/js-examples/tree/master/promises-test">js-examples</a> 儲存庫找到。 你也可以<a href="https://mdn.github.io/js-examples/promises-test/">see it in action</a>。每個步驟都附以註解,讓你能逐步遵隨 Promise 與 XHR 架構。</p>
+
+<h2 id="規範">規範</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Specification</th>
+ <th scope="col">Status</th>
+ <th scope="col">Comment</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('ES2015', '#sec-promise-objects', 'Promise')}}</td>
+ <td>{{Spec2('ES2015')}}</td>
+ <td>Initial definition in an ECMA standard.</td>
+ </tr>
+ <tr>
+ <td>{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}</td>
+ <td>{{Spec2('ESDraft')}}</td>
+ <td> </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="瀏覽器相容性">瀏覽器相容性</h2>
+
+<p class="hidden">To contribute to this compatibility data, please write a pull request against this repository: <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a>.</p>
+
+<p>{{Compat("javascript.builtins.Promise")}}</p>
+
+<h2 id="參見">參見</h2>
+
+<ul>
+ <li><a href="/zh-TW/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li>
+ <li><a href="http://promisesaplus.com/">Promises/A+ specification</a></li>
+ <li><a href="https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53">Venkatraman.R - JS Promise (Part 1, Basics)</a></li>
+ <li><a href="https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski">Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)</a></li>
+ <li><a href="https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction">Venkatraman.R - Tools for Promises Unit Testing</a></li>
+ <li><a href="http://www.html5rocks.com/en/tutorials/es6/promises/">Jake Archibald: JavaScript Promises: There and Back Again</a></li>
+ <li><a href="http://de.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript">Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Patterns in JavaScript</a></li>
+ <li><a href="http://www.mattgreer.org/articles/promises-in-wicked-detail/">Matt Greer: JavaScript Promises ... In Wicked Detail</a></li>
+ <li><a href="https://www.promisejs.org/">Forbes Lindesay: promisejs.org</a></li>
+ <li><a href="http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Nolan Lawson: We have a problem with promises — Common mistakes with promises</a></li>
+ <li><a href="https://github.com/jakearchibald/es6-promise/">Promise polyfill</a></li>
+ <li><a href="https://www.udacity.com/course/javascript-promises--ud898">Udacity: JavaScript Promises</a></li>
+</ul>