From 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:43:23 -0500 Subject: initial commit --- .../global_objects/promise/all/index.html | 207 ++++++++++++++++ .../global_objects/promise/catch/index.html | 189 ++++++++++++++ .../global_objects/promise/finally/index.html | 102 ++++++++ .../reference/global_objects/promise/index.html | 256 +++++++++++++++++++ .../global_objects/promise/prototype/index.html | 64 +++++ .../global_objects/promise/race/index.html | 171 +++++++++++++ .../global_objects/promise/reject/index.html | 72 ++++++ .../global_objects/promise/resolve/index.html | 142 +++++++++++ .../global_objects/promise/then/index.html | 271 +++++++++++++++++++++ 9 files changed, 1474 insertions(+) create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/all/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/catch/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/finally/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/prototype/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/race/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/reject/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/resolve/index.html create mode 100644 files/zh-tw/web/javascript/reference/global_objects/promise/then/index.html (limited to 'files/zh-tw/web/javascript/reference/global_objects/promise') diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/all/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/all/index.html new file mode 100644 index 0000000000..eb18ce63f9 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/all/index.html @@ -0,0 +1,207 @@ +--- +title: Promise.all() +slug: Web/JavaScript/Reference/Global_Objects/Promise/all +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/all +--- +
{{JSRef}}
+ +

Promise.all() 方法回傳一個 {{jsxref("Promise")}} 物件,當引數 iterable 中所有的 promises 都被實現(resolved),或引數 iterable 不含任何 promise 時,被實現。或以第一個被拒絕的 promise 的原因被拒絕。

+ +

語法

+ +
Promise.all(iterable);
+ +
+
iterable
+
一個 iterable 物件像是 {{jsxref("Array")}} 或 {{jsxref("String")}}。
+
+ +

回傳值

+ + + +

描述

+ +

此方法在聚集(aggregating)多個 promises 的結果時很有幫助。

+ +

實現(Fulfillment):
+ 若傳入空的 iterable,此方法(同步地)回傳一個已被解決的 promise。若所有傳入的 promises 都被實現,或都不是 promise,Promise.all 回傳的 promise 被非同步地實現。無論是哪個情形,回傳一個以 iterable 其內所有值(包含非 promise 值)作為引數的陣列被實現。
+  

+ +

拒絕(Rejection):
+ 若任一個傳入的 promise 被拒絕,Promise.all 非同步地以其值被拒絕,無論其他 promises 是否被解決。

+ +

範例

+ +

使用 Promise.all

+ +

Promise.all 等到全部實現(或一個拒絕)。

+ +
var p1 = Promise.resolve(3);
+var p2 = 1337;
+var p3 = new Promise((resolve, reject) => {
+  setTimeout(resolve, 100, 'foo');
+});
+
+Promise.all([p1, p2, p3]).then(values => {
+  console.log(values); // [3, 1337, "foo"]
+});
+ +

若 iterable 含非 promise 值,它們將被忽略,但依然會被記入回傳 promise 陣列值(若被實現):

+ +
// this will be counted as if the iterable passed is empty, so it gets fulfilled
+var p = Promise.all([1,2,3]);
+// this will be counted as if the iterable passed contains only the resolved promise with value "444", so it gets fulfilled
+var p2 = Promise.all([1,2,3, Promise.resolve(444)]);
+// this will be counted as if the iterable passed contains only the rejected promise with value "555", so it gets rejected
+var p3 = Promise.all([1,2,3, Promise.reject(555)]);
+
+// using setTimeout we can execute code after the stack is empty
+setTimeout(function(){
+    console.log(p);
+    console.log(p2);
+    console.log(p3);
+});
+
+// logs
+// Promise { <state>: "fulfilled", <value>: Array[3] }
+// Promise { <state>: "fulfilled", <value>: Array[4] }
+// Promise { <state>: "rejected", <reason>: 555 }
+ +

Promise.all 的非同步與同步性質

+ +

以下例子驗證了 Promise.all 的非同步性質(asynchronicity)(或同步性質(synchronicity),若傳入的 iterable 是空的):

+ +
// we are passing as argument an array of promises that are already resolved,
+// to trigger Promise.all as soon as possible
+var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
+
+var p = Promise.all(resolvedPromisesArray);
+// immediately logging the value of p
+console.log(p);
+
+// using setTimeout we can execute code after the stack is empty
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: Array[2] }
+
+ +

Promise.all 被拒絕時發生一樣的事情:

+ +
var mixedPromisesArray = [Promise.resolve(33), Promise.reject(44)];
+var p = Promise.all(mixedPromisesArray);
+console.log(p);
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p);
+});
+
+// logs
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "rejected", <reason>: 44 }
+
+ +

注意!Promise.all 同步地被解決若且唯若傳入的 iterable 為空:

+ +
var p = Promise.all([]); // will be immediately resolved
+var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
+console.log(p);
+console.log(p2)
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p2);
+});
+
+// logs
+// Promise { <state>: "fulfilled", <value>: Array[0] }
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: Array[2] }
+
+ +

Promise.all 的失敗優先(fail-fast)行為

+ +

當任一個陣列成員被拒絕則 Promise.all 被拒絕。例如,若傳入四個將在一段時間後被解決的 promises,而其中一個立刻被拒絕,則 Promise.all 將立刻被拒絕。

+ +
var p1 = new Promise((resolve, reject) => {
+  setTimeout(resolve, 1000, 'one');
+});
+var p2 = new Promise((resolve, reject) => {
+  setTimeout(resolve, 2000, 'two');
+});
+var p3 = new Promise((resolve, reject) => {
+  setTimeout(resolve, 3000, 'three');
+});
+var p4 = new Promise((resolve, reject) => {
+  setTimeout(resolve, 4000, 'four');
+});
+var p5 = new Promise((resolve, reject) => {
+  reject('reject');
+});
+
+Promise.all([p1, p2, p3, p4, p5]).then(values => {
+  console.log(values);
+}, reason => {
+  console.log(reason)
+});
+
+//From console:
+//"reject"
+
+//You can also use .catch
+Promise.all([p1, p2, p3, p4, p5]).then(values => {
+  console.log(values);
+}).catch(reason => {
+  console.log(reason)
+});
+
+//From console:
+//"reject"
+
+
+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise.all', 'Promise.all')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise.all', 'Promise.all')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript.builtins.Promise.all")}}

+ +

參見

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/catch/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/catch/index.html new file mode 100644 index 0000000000..d06036c11e --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/catch/index.html @@ -0,0 +1,189 @@ +--- +title: Promise.prototype.catch() +slug: Web/JavaScript/Reference/Global_Objects/Promise/catch +tags: + - EMCAScript 2015 + - JavaScript + - Method + - Promise + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/catch +--- +
{{JSRef}}
+ +

catch() 方法只處理 Promise 的被拒絕狀態,並回傳一個新的 Promise 物件。此方法的行為等同於呼叫 {{jsxref("Promise.then", "Promise.prototype.then(undefined, onRejected)")}}。

+ +

語法

+ +
p.catch(onRejected);
+
+p.catch(function(reason) {
+   // rejection
+});
+
+ +

參數

+ +
+
onRejected
+
一個 {{jsxref("Function")}} ,在 Promise 被拒絕時被呼叫。這個函式有一個引數: +
+
reason
+
失敗訊息。
+
+ 若 onRejected 拋出一個錯誤或回傳一個被拒絕的 Promise,則 catch() 回傳的 Promise 被拒絕;其他情形都是被實現。
+
+ +

回傳值

+ +

呼叫(catch 的 promise)物件,內部呼叫 Promise.prototype.then,傳入引數 undefined 及 onRejected;接著以之結果回傳(結果為 {{jsxref("Promise")}})。

+ +

內部呼叫演示:

+ +
// overriding original Promise.prototype.then/catch just to add some logs
+(function(Promise){
+    var originalThen = Promise.prototype.then;
+    var originalCatch = Promise.prototype.catch;
+
+    Promise.prototype.then = function(){
+        console.log('> > > > > > called .then on %o with arguments: %o', this, arguments);
+        return originalThen.apply(this, arguments);
+    };
+    Promise.prototype.catch = function(){
+        console.log('> > > > > > called .catch on %o with arguments: %o', this, arguments);
+        return originalCatch.apply(this, arguments);
+    };
+
+})(this.Promise);
+
+
+
+// calling catch on an already resolved promise
+Promise.resolve().catch(function XXX(){});
+
+// logs:
+// > > > > > > called .catch on Promise{} with arguments: Arguments{1} [0: function XXX()]
+// > > > > > > called .then on Promise{} with arguments: Arguments{2} [0: undefined, 1: function XXX()]
+
+ +

描述

+ +

catch 方法在處理 promise 組合的錯誤時很有幫助。

+ +

範例

+ +

使用及串接 catch 方法

+ +
var p1 = new Promise(function(resolve, reject) {
+  resolve('Success');
+});
+
+p1.then(function(value) {
+  console.log(value); // "Success!"
+  throw 'oh, no!';
+}).catch(function(e) {
+  console.log(e); // "oh, no!"
+}).then(function(){
+  console.log('after a catch the chain is restored');
+}, function () {
+  console.log('Not fired due to the catch');
+});
+
+// The following behaves the same as above
+p1.then(function(value) {
+  console.log(value); // "Success!"
+  return Promise.reject('oh, no!');
+}).catch(function(e) {
+  console.log(e); // "oh, no!"
+}).then(function(){
+  console.log('after a catch the chain is restored');
+}, function () {
+  console.log('Not fired due to the catch');
+});
+
+ +

拋出例外時的陷阱

+ +
// Throwing an error will call the catch method most of the time
+var p1 = new Promise(function(resolve, reject) {
+  throw 'Uh-oh!';
+});
+
+p1.catch(function(e) {
+  console.log(e); // "Uh-oh!"
+});
+
+// Errors thrown inside asynchronous functions will act like uncaught errors
+var p2 = new Promise(function(resolve, reject) {
+  setTimeout(function() {
+    throw 'Uncaught Exception!';
+  }, 1000);
+});
+
+p2.catch(function(e) {
+  console.log(e); // This is never called
+});
+
+// Errors thrown after resolve is called will be silenced
+var p3 = new Promise(function(resolve, reject) {
+  resolve();
+  throw 'Silenced Exception!';
+});
+
+p3.catch(function(e) {
+   console.log(e); // This is never called
+});
+ +

如果 Promise 被實現

+ +
//Create a promise which would not call onReject
+var p1 = Promise.resolve("calling next");
+
+var p2 = p1.catch(function (reason) {
+    //This is never called
+    console.log("catch p1!");
+    console.log(reason);
+});
+
+p2.then(function (value) {
+    console.log("next promise's onFulfilled"); /* next promise's onFulfilled */
+    console.log(value); /* calling next */
+}, function (reason) {
+    console.log("next promise's onRejected");
+    console.log(reason);
+});
+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise.prototype.catch', 'Promise.prototype.catch')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise.prototype.catch', 'Promise.prototype.catch')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript.builtins.Promise.catch")}}

+ +

參見

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/finally/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/finally/index.html new file mode 100644 index 0000000000..eef15faf9a --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/finally/index.html @@ -0,0 +1,102 @@ +--- +title: Promise.prototype.finally() +slug: Web/JavaScript/Reference/Global_Objects/Promise/finally +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/finally +--- +
{{JSRef}}
+ +

finally() 方法會回傳一個 {{jsxref("Promise")}}。當 promise 被 settled 後,無論其結果是 fulfilled 還是 rejected ,都會執行指定的回呼函數。它提供了一個讓 Promise 在被確認後,無論是 fulfilled 或是 rejected 都會執行某些程式碼的一種手段。

+ +

這樣可以避免你在 promise 的 {{jsxref("Promise.then", "then()")}} 和 {{jsxref("Promise.catch", "catch()")}} 重複處理相同的程式碼。

+ +

Syntax

+ +
p.finally(onFinally);
+
+p.finally(function() {
+   // settled(fulfilled 或 rejected)
+});
+
+ +

Parameters

+ +
+
onFinally
+
Promise settled 後呼叫的 {{jsxref("Function")}}。
+
+ +

Return value

+ +

回傳 {{jsxref("Promise")}} 當 finally 的處理函數 onFinally 被指定時。

+ +

Description

+ +

當你希望在 promise settled 後且不關心它的結果為何時,執行一些處理或清理的工作, finally() 方法會很有幫助。

+ +

finally() 方法非常類似於 .then(onFinally, onFinally) 的呼叫方式,但仍有一些差異:

+ + + +
+

備註: 在 finally 回呼中使用 throw (或回傳 rejected promise)會導致新的 promise 被 reject , reject 的原因則是呼叫 throw() 時所指定的值。

+
+ +

Examples

+ +
let isLoading = true;
+
+fetch(myRequest).then(function(response) {
+    var contentType = response.headers.get("content-type");
+    if(contentType && contentType.includes("application/json")) {
+      return response.json();
+    }
+    throw new TypeError("Oops, we haven't got JSON!");
+  })
+  .then(function(json) { /* process your JSON further */ })
+  .catch(function(error) { console.log(error); })
+  .finally(function() { isLoading = false; });
+
+
+ + + +

Specifications

+ + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ESDraft', '#sec-promise.prototype.finally', 'Promise.prototype.finally')}}{{Spec2('ESDraft')}}
+ +

Browser compatibility

+ + + +

{{Compat("javascript.builtins.Promise.finally")}}

+ +

See also

+ + 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 +--- +
{{JSRef}}
+ +

Promise 物件代表一個即將完成、或失敗的非同步操作,以及它所產生的值。

+ +
+

此條目為介紹 Promise 建構式。要瞭解 Promise 相關使用方式,請先參考使用 Promise。Promise 建構式主要用於包裹尚未支援 Promise 的函式。

+
+ +
{{EmbedInteractiveExample("pages/js/promise-constructor.html")}}
+ + + + + +

語法

+ +
new Promise( /* executor */ function(resolve, reject) { ... } );
+ +

參數

+ +
+
executor
+
為一個依序接收兩個參數的函式:resolvereject(實現及拒絕回呼函式)。在 Promise 實作中,executor 函式在傳入參數 resolvereject 後會立刻執行(executor 函式會在 Promise 建構式回傳 Promise 物件前被執行)。resolvereject 函式,會在被個別呼叫時,個別執行之。通常 executor 函式會發起一些非同步操作。接著,成功完成後執行 resolve 以完成 promise;或如果有錯誤,執行 rejects
如果 executor 函式在執行中拋出錯誤,promise 會被拒絕(rejected),回傳值也將被忽略。
+
+ +

描述

+ +

Promise 會代理一個建立時,不用預先得知的值。它使你能夠繫結(associate)著發動非同步操作後,最終的成功值(success value)或失敗訊息(failure reason)的處理函式(handlers)。這讓非同步方法回傳值的方式很像同步方法,但不是回傳最終結果:非同步方法回傳一個 promise 物件作為未來某時間點的值。

+ +

一個 Promise 物件處於以下幾種狀態:

+ + + +

一個處於擱置狀態的 promise 能以一個值被實現(fulfilled),或是以一個原因或錯誤而被拒絕(rejected)。當上述任一狀態轉換發生時,那些透過 then 方法所繫結(associated)的處理函式列隊就會依序被調用。(若一個 promise 已被實現或拒絕,繫結(attached)於它的處理函式將立即被呼叫,因此完成非同步操作與繫結處理函式之間不存在競爭條件(race condition)。)

+ +

由於 {{jsxref("Promise.then", "Promise.prototype.then()")}} 以及 {{jsxref("Promise.catch", "Promise.prototype.catch()")}} 方法都回傳 promise,它們可以被串接。

+ +

+ +
+

容易混淆: 許多其他語言擁有機制用來惰性求值(lazy evaluation)及延遲(deferring)運算,它們也被稱作“promises” — e.g. Scheme. 然而在 JavaScript 中 Promises 代表那些(已經)發生中(happening)的程序,它們可以繫結回呼函式。若您要找的是惰性求值表示式,考慮不帶參數的 arrow functionf = () => expression 來建立惰性求值表示式,並透過 f() 進行求值.

+
+ +
+

Note: 一個被實現或拒絕,但不處於 pending 的 promise 被稱作被解決(settled)。您也會見到使用解決(resolved)一詞來描述 promises — 這代表 promises 被實現(fulfilled)了。States and fates 這篇文章包含了更多 promises 的專有名詞。

+
+ +

屬性

+ +
+
Promise.length
+
長度屬性,值固定為 1。(建構式參數數目).
+
{{jsxref("Promise.prototype")}}
+
Promise 建構式的原型(prototype).
+
+ +

方法

+ +
+
{{jsxref("Promise.all", "Promise.all(iterable)")}}
+
回傳一個 promise,當在引數 iterable 中所有 promises 都被實現時被實現,或在引數 iterable 中有一個 promise 被拒絕時立刻被拒絕。若回傳的 promise 被實現,它將以一個實現值的陣列被實現,其順序與 iterable 中的 promises 相同。若回傳的 promise 被拒絕,它將以失敗訊息被拒絕,此訊息來自第一個在 iterable 中被拒絕的 promise。這個方法在聚集許多 promises 的結果時很有效。
+
{{jsxref("Promise.race", "Promise.race(iterable)")}}
+
回傳一個被實現或拒絕的 promise,當 iterable 中有一個 promise 被實現或拒絕時。
+
+ +
+
{{jsxref("Promise.reject", "Promise.reject(reason)")}}
+
回傳一個以失敗訊息拒絕的 promise
+
+ +
+
{{jsxref("Promise.resolve", "Promise.resolve(value)")}}
+
回傳一個以 value 實現的 promise。若該值為 thenable (i.e. 具有 then 方法),回傳的 promise 將跟隨(follow)之,採用她的最終狀態; 在其他情形回傳的 promise 將以 value 被實現。一般來說,當您不知道 value 是否為 promise,使用 {{jsxref("Promise.resolve", "Promise.resolve(value)")}},將回傳值以 promise 作處理。
+
+ +

Promise 原型

+ +

屬性

+ +

{{page('zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/prototype','屬性')}}

+ +

方法

+ +

{{page('zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/prototype','方法')}}

+ +

建立 Promise

+ +

一個 Promise 物件透過 new 及其建構式建立。這個建構式接收一個叫作”執行器函式(executor function)“的引數。此函式接收兩個函式作為引數。第一個函式(resolve)在非同步作業成功完成時,以該作業之結果值被呼叫。第二個函式(reject)在作業失敗時,以失敗訊息,通常是一個 error object,被呼叫。

+ +
const myFirstPromise = new Promise((resolve, reject) => {
+  // 執行一些非同步作業,最終呼叫:
+  //
+  //   resolve(someValue); // 實現
+  // 或
+  //   reject("failure reason"); // 拒絕
+});
+
+ +

要提供一個函式 promise 功能,讓它回傳一個 promise 即可:

+ +
function myAsyncFunction(url) {
+  return new Promise((resolve, reject) => {
+    const xhr = new XMLHttpRequest();
+    xhr.open("GET", url);
+    xhr.onload = () => resolve(xhr.responseText);
+    xhr.onerror = () => reject(xhr.statusText);
+    xhr.send();
+  });
+};
+ +

範例

+ +

入門範例

+ +
let myFirstPromise = new Promise((resolve, reject) => {
+  // 當非同步作業成功時,呼叫 resolve(...),而失敗時則呼叫 reject(...)。
+  // 在這個例子中,使用 setTimeout(...) 來模擬非同步程式碼。
+  // 在實務中,您將可能使用像是 XHR 或者一個 HTML5 API.
+  setTimeout(function(){
+    resolve("Success!"); // Yay!非常順利!
+  }, 250);
+});
+
+myFirstPromise.then((successMessage) => {
+  // successMessage 是任何您由上方 resolve(...) 傳入的東西。
+  // 在此僅作為成功訊息,但是它不一定是字串。
+  console.log("Yay! " + successMessage);
+});
+
+ +

進階範例

+ + + +

這個小範例演示了 Promise 的運作機制。每當 {{HTMLElement("button")}} 被點擊時,testPromise() 方法被呼叫。每次點擊將透過 {{domxref("window.setTimeout()")}} 建立一個將在 1-3 秒內隨機地被實現的 promise,供 promise 計數(一個從 1 開始的數值)。建構式 Promise() 被用來建立 promise。

+ +

promise 的實現值單純地經由一個實現回呼函式 {{jsxref("Promise.prototype.then()","p1.then()")}} 被印出。下以一些文字紀錄來展現方法中同步的與非同步處理 promise 的部分是如何分離彼此。

+ +
'use strict';
+var promiseCount = 0;
+
+function testPromise() {
+    let thisPromiseCount = ++promiseCount;
+
+    let log = document.getElementById('log');
+    log.insertAdjacentHTML('beforeend', thisPromiseCount +
+        ') Started (<small>Sync code started</small>)<br/>');
+
+    // 建立一個新的 promise:此 promise 承諾一個數值計數, 由 1 開始(等待約 2 秒)
+    let p1 = new Promise(
+        // 這個解決器函數(resolver function)呼叫實現或
+        // 拒絕 promise。
+        (resolve, reject) => {
+            log.insertAdjacentHTML('beforeend', thisPromiseCount +
+                ') Promise started (<small>Async code started</small>)<br/>');
+            // 在此例子單純用來產生非同步特性。
+            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 (<small>Async code terminated</small>)<br/>');
+        })
+    .catch(
+        // 印出失敗訊息(rejection reason)
+        (reason) => {
+            console.log('Handle rejected promise ('+reason+') here.');
+        });
+
+    log.insertAdjacentHTML('beforeend', thisPromiseCount +
+        ') Promise made (<small>Sync code terminated</small>)<br/>');
+}
+ +

*譯註:resolver function 即 executor function。

+ + + +

這個範例從點擊按鈕開始。您的瀏覽器需要支援 Promise。在短時間內點擊按鈕許多次,您甚至將看到不同的 promises 一個接一個地被實現。

+ +

{{EmbedLiveSample("Advanced_Example", "500", "200")}}

+ +

使用 XHR 載入圖片

+ +

另一個使用 Promise and XMLHttpRequest 來載入圖片的簡單例子可以在 MDN GitHub js-examples 儲存庫找到。 你也可以see it in action。每個步驟都附以註解,讓你能逐步遵隨 Promise 與 XHR 架構。

+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise-objects', 'Promise')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript.builtins.Promise")}}

+ +

參見

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/prototype/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/prototype/index.html new file mode 100644 index 0000000000..476c52f7a3 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/prototype/index.html @@ -0,0 +1,64 @@ +--- +title: Promise.prototype +slug: Web/JavaScript/Reference/Global_Objects/Promise/prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Promise +--- +
{{JSRef}}
+ +

Promise.prototype 屬性代表了 {{jsxref("Promise")}} 建構式的原型物件。

+ +
{{js_property_attributes(0,0,0)}}
+ +

描述

+ +

所有 {{jsxref("Promise")}} 實例都繼承自 {{jsxref("Promise.prototype")}}。您可以使用建構式的原型物件來增加屬性或方法到所有的 Promise 實例。

+ +

屬性

+ +
+
Promise.prototype.constructor
+
回傳一個建立實例原型(instance's prototype)的函式。預設為 {{jsxref("Promise")}} 函數。
+
+ +

方法

+ +
+
{{jsxref("Promise.catch", "Promise.prototype.catch(onRejected)")}}
+
繫結一個拒絕回呼函式(rejection handler callback)到 promise,當它被呼叫時回傳一個以回傳值作解析的新 promise,或者當 promise 被實現時以原值作解析。
+
{{jsxref("Promise.then", "Promise.prototype.then(onFulfilled, onRejected)")}}
+
繫結實現或拒絕回呼函式到 promise,回傳一個以 handler 之回傳值作解析的新 promise,或者當 promise 未處理(not handled)時以原值作解析。(i.e. 比如相關聯的 onFulfilled 或 onRejected 不是函式。)
+
+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES6', '#sec-promise.prototype', 'Promise.prototype')}}{{Spec2('ES6')}}Initial definition.
{{SpecName('ESDraft', '#sec-promise.prototype', 'Promise.prototype')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript/promise","Promise.prototype")}}

+ +

參見

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/race/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/race/index.html new file mode 100644 index 0000000000..9f0d8b4d2e --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/race/index.html @@ -0,0 +1,171 @@ +--- +title: Promise.race() +slug: Web/JavaScript/Reference/Global_Objects/Promise/race +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/race +--- +
{{JSRef}}
+ +

Promise.race(iterable) 方法回傳一個 promise 物件,此 promise 物件會於 iterable 引數中任一個 promise 轉為 resolve 或 rejected 時立即轉變成 resolve 或 rejected,並且接收其成功值或失敗訊息。

+ +

語法

+ +
Promise.race(iterable);
+ +

參數

+ +
+
iterable
+
一個 iterable 物件,像是 {{jsxref("Array")}}. 請參考可迭代協議
+
+ +

回傳值

+ +

當傳入的 iterable 中有 promise 被實現或拒絕時,立刻回傳被實現或拒絕的 {{jsxref("Promise")}}。

+ +

描述

+ +

race 函式回傳一個與傳入的 iterable 之中第一個被解決(settled)的 promise 相同方式被解決(且以相同值)的 Promise

+ +

範例

+ +

Promise.race 的非同步性質

+ +

以下例子演示了 Promise.race 的非同步性質:

+ +
// we are passing as argument an array of promises that are already resolved,
+// to trigger Promise.race as soon as possible
+var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
+
+var p = Promise.race(resolvedPromisesArray);
+// immediately logging the value of p
+console.log(p);
+
+// using setTimeout we can execute code after the stack is empty
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: 33 }
+ +

一個空的 iterable 造成回傳的 promise 永久擱置:

+ +
var foreverPendingPromise = Promise.race([]);
+console.log(foreverPendingPromise);
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(foreverPendingPromise);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "pending" }
+
+ +

若 iterable 中有一個或多個非 promise 值且/或一個已經被實現/解決的 promise,Promise.race 將以陣列中第一個這樣的值解決:

+ +
var foreverPendingPromise = Promise.race([]);
+var alreadyResolvedProm = Promise.resolve(666);
+
+var arr = [foreverPendingPromise, alreadyResolvedProm, "non-Promise value"];
+var arr2 = [foreverPendingPromise, "non-Promise value", Promise.resolve(666)];
+var p = Promise.race(arr);
+var p2 = Promise.race(arr2);
+
+console.log(p);
+console.log(p2);
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p);
+    console.log(p2);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: 666 }
+// Promise { <state>: "fulfilled", <value>: "non-Promise value" }
+
+ +

使用 Promise.race – 及 setTimeout 的範例

+ +
var p1 = new Promise(function(resolve, reject) {
+    setTimeout(resolve, 500, 'one');
+});
+var p2 = new Promise(function(resolve, reject) {
+    setTimeout(resolve, 100, 'two');
+});
+
+Promise.race([p1, p2]).then(function(value) {
+  console.log(value); // "two"
+  // Both resolve, but p2 is faster
+});
+
+var p3 = new Promise(function(resolve, reject) {
+    setTimeout(resolve, 100, 'three');
+});
+var p4 = new Promise(function(resolve, reject) {
+    setTimeout(reject, 500, 'four');
+});
+
+Promise.race([p3, p4]).then(function(value) {
+  console.log(value); // "three"
+  // p3 is faster, so it resolves
+}, function(reason) {
+  // Not called
+});
+
+var p5 = new Promise(function(resolve, reject) {
+    setTimeout(resolve, 500, 'five');
+});
+var p6 = new Promise(function(resolve, reject) {
+    setTimeout(reject, 100, 'six');
+});
+
+Promise.race([p5, p6]).then(function(value) {
+  // Not called
+}, function(reason) {
+  console.log(reason); // "six"
+  // p6 is faster, so it rejects
+});
+
+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise.race', 'Promise.race')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise.race', 'Promise.race')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript.builtins.Promise.race")}}

+ +

參見

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/reject/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/reject/index.html new file mode 100644 index 0000000000..0c41a37509 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/reject/index.html @@ -0,0 +1,72 @@ +--- +title: Promise.reject() +slug: Web/JavaScript/Reference/Global_Objects/Promise/reject +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/reject +--- +
{{JSRef}}
+ +

Promise.reject(reason) 方法回傳一個以 reason 拒絕的 Promise 物件。

+ +

語法

+ +
Promise.reject(reason);
+ +

參數

+ +
+
reason
+
Promise 的失敗訊息。
+
+ +

回傳值

+ +

一個以 reason 拒絕的 {{jsxref("Promise")}}。

+ +

描述

+ +

靜態函式 Promise.reject 回傳一個被拒絕的 Promise。由於除錯目的及選擇性錯誤捕捉(selective error catching),使用一個 instanceof {{jsxref("Error")}} 作為 reason 是很有幫助的。

+ +

範例

+ +

使用靜態方法 Promise.reject()

+ +
Promise.reject(new Error('fail')).then(function(error) {
+  // not called
+}, function(error) {
+  console.log(error); // Stacktrace
+});
+ +

Specifications

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise.reject', 'Promise.reject')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise.reject', 'Promise.reject')}}{{Spec2('ESDraft')}} 
+ +

Browser compatibility

+ + + +

{{Compat("javascript.builtins.Promise.reject")}}

+ +

See also

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/resolve/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/resolve/index.html new file mode 100644 index 0000000000..e2d460a7e3 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/resolve/index.html @@ -0,0 +1,142 @@ +--- +title: Promise.resolve() +slug: Web/JavaScript/Reference/Global_Objects/Promise/resolve +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/resolve +--- +
{{JSRef}}
+ +

Promise.resolve(value) 方法回傳一個以 value 判定結果的 {{jsxref("Promise")}} 物件。若 value 是個 thenable (例如,具有 {{jsxref("Promise.then", "\"then\"方法")}}),則回傳的 promise 將依其結果採取其最終狀態;若 value 是 promise,則作為呼叫 Promise.resolve 之結果;其他情形都將回傳以 value 實現的 promise。

+ +

語法

+ +
Promise.resolve(value);
+Promise.resolve(promise);
+Promise.resolve(thenable);
+
+ +

參數

+ +
+
value
+
將被 Promise 實現的引數(argument)。可以是個 Promise 或待解決的 thenable。
+
+ +

回傳值

+ +

以 value 或作為 value 的 promise 解決的 {{jsxref("Promise")}}。

+ +

描述

+ +

靜態函式 Promise.resolve 回傳判定後的 Promise。

+ +

範例

+ +

使用 Promise.resolve 靜態方法

+ +
Promise.resolve('Success').then(function(value) {
+  console.log(value); // "Success"
+}, function(value) {
+  // not called
+});
+
+ +

判定陣列

+ +
var p = Promise.resolve([1,2,3]);
+p.then(function(v) {
+  console.log(v[0]); // 1
+});
+
+ +

判定另一個 Promise

+ +
var original = Promise.resolve(33);
+var cast = Promise.resolve(original);
+cast.then(function(value) {
+  console.log('value: ' + value);
+});
+console.log('original === cast ? ' + (original === cast));
+
+// logs, in order:
+// original === cast ? true
+// value: 33
+
+ +

由於 handlers 是非同步地被調用而導致相反的紀錄順序。經由這篇文章了解 then 如何運作。

+ +

判定 thenables 及拋出 Errors

+ +
// Resolving a thenable object
+var p1 = Promise.resolve({
+  then: function(onFulfill, onReject) { onFulfill('fulfilled!'); }
+});
+console.log(p1 instanceof Promise) // true, object casted to a Promise
+
+p1.then(function(v) {
+    console.log(v); // "fulfilled!"
+  }, function(e) {
+    // not called
+});
+
+// Thenable throws before callback
+// Promise rejects
+var thenable = { then: function(resolve) {
+  throw new TypeError('Throwing');
+  resolve('Resolving');
+}};
+
+var p2 = Promise.resolve(thenable);
+p2.then(function(v) {
+  // not called
+}, function(e) {
+  console.log(e); // TypeError: Throwing
+});
+
+// Thenable throws after callback
+// Promise resolves
+var thenable = { then: function(resolve) {
+  resolve('Resolving');
+  throw new TypeError('Throwing');
+}};
+
+var p3 = Promise.resolve(thenable);
+p3.then(function(v) {
+  console.log(v); // "Resolving"
+}, function(e) {
+  // not called
+});
+
+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise.resolve', 'Promise.resolve')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise.resolve', 'Promise.resolve')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript.builtins.Promise.resolve")}}

+ +

參見

+ + diff --git a/files/zh-tw/web/javascript/reference/global_objects/promise/then/index.html b/files/zh-tw/web/javascript/reference/global_objects/promise/then/index.html new file mode 100644 index 0000000000..19682d0199 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/promise/then/index.html @@ -0,0 +1,271 @@ +--- +title: Promise.prototype.then() +slug: Web/JavaScript/Reference/Global_Objects/Promise/then +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/then +--- +
{{JSRef}}
+ +

then() 方法回傳一個 {{domxref("Promise")}} 物件。它接收兩個引數: Promise 在成功及失敗情況時的回呼函式。

+ +
+

如果有一個或兩個引數被省略,或為非函式(non-functions),則 then 將處於遺失 handler(s) 的狀態,但不會產生錯誤。若發起 then 之 Promise 採取了一個狀態(實現(fulfillment)或拒絕(rejection))而 then 沒有處理它的函式,一個不具有額外 handlers 的新 Promise 物件將被建立,單純採取原 Promise 其最終狀態。

+
+ +

語法

+ +
p.then(onFulfilled[, onRejected]);
+
+p.then(function(value) {
+  // fulfillment
+}, function(reason) {
+  // rejection
+});
+
+ +

參數

+ +
+
onFulfilled
+
一個 {{jsxref("Function")}},當 Promise 被實現(fulfilled)時被呼叫。此函式接收一個實現值(fullfillment value)作為引數。
+
onRejected {{optional_inline}}
+
一個 {{jsxref("Function")}},當 Promise 被拒絕(rejected)時被呼叫。此函式接收一個失敗訊息(rejection reason)作為引數。
+
+ +

回傳值

+ +

一個進入擱置(pending)狀態的 {{jsxref("Promise")}}。(只要堆疊一空)handler 函式非同步地(asynchronously)被呼叫。在調用 handler 後,若 handler 函式:

+ + + +

以下例子展示 then 方法的非同步性質(asynchronicity)。

+ +
// 使用一個已實現的 promise,'then' 區塊將立即被觸發,但是它的 handlers 將是非同步地被觸發,如同 console.logs 所示
+var resolvedProm = Promise.resolve(33);
+
+var thenProm = resolvedProm.then(function(value){
+    console.log("我在 main stack 之後被呼叫。收到及將回傳的值為:" + value);
+    return value;
+});
+// 立即紀錄 thenProm
+console.log(thenProm);
+
+// 我們可以使用 setTimeout 以延遲(postpone)函式執行直到堆疊為空
+setTimeout(function(){
+    console.log(thenProm);
+});
+
+
+// 紀錄結果,依序為:
+// Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
+// "我在 main stack 之後被呼叫。收到及將回傳的值為:33"
+// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 33}
+
+ +

描述

+ +

因為 then 和 {{jsxref("Promise.prototype.catch()")}} 方法都回傳 promises,它們可以被串接 — 稱為組合(composition)。

+ +

範例

+ +

運用 then 方法

+ +
var p1 = new Promise( (resolve, reject) => {
+  resolve('Success!');
+  // or
+  // reject ("Error!");
+} );
+
+p1.then( value => {
+  console.log(value); // Success!
+}, reason => {
+  console.log(reason); // Error!
+} );
+
+ +

串接

+ +

then 方法回傳一個 Promise 而可以進行方法串接(method chaining)。

+ +

如果傳入 then 的 handler 函式回傳一個 promise,一個等價的 Promise 將被展現給方法串接中的下一個 then 。以下程式碼片段透過 setTimout 函式模擬非同步程式碼。

+ +
Promise.resolve('foo')
+  // 1. Receive "foo" concatenate "bar" to it and resolve that to the next then
+  .then(function(string) {
+    return new Promise(function(resolve, reject) {
+      setTimeout(function() {
+        string += 'bar';
+        resolve(string);
+      }, 1);
+    });
+  })
+  // 2. receive "foobar", register a callback function to work on that string
+  // and print it to the console, but not before return the unworked on
+  // string to the next then
+  .then(function(string) {
+    setTimeout(function() {
+      string += 'baz';
+      console.log(string);
+    }, 1)
+    return string;
+  })
+  // 3. print helpful messages about how the code in this section will be run
+  // before string is actually processed by the mocked asynchronous code in the
+  // prior then block.
+  .then(function(string) {
+    console.log("Last Then:  oops... didn't bother to instantiate and return " +
+                "a promise in the prior then so the sequence may be a bit " +
+                "surprising");
+
+    // Note that `string` will not have the 'baz' bit of it at this point. This
+    // is because we mocked that to happen asynchronously with a setTimeout function
+    console.log(string);
+  });
+ +

當 handler 僅回傳一個值,實際上它將回傳 Promise.resolve(<value returned by whichever handler was called>).

+ +
var p2 = new Promise(function(resolve, reject) {
+  resolve(1);
+});
+
+p2.then(function(value) {
+  console.log(value); // 1
+  return value + 1;
+}).then(function(value) {
+  console.log(value + '- This synchronous usage is virtually pointless'); // 2- This synchronous usage is virtually pointless
+});
+
+p2.then(function(value) {
+  console.log(value); // 1
+});
+
+ +

若函式拋出一個錯誤或回傳一個被否決的 Promise,then 也將回傳一個被否決的 Promise。

+ +
Promise.resolve()
+  .then( () => {
+    // 使 .then() 回傳一個被否決的 Promise
+    throw 'Oh no!';
+  })
+  .then( () => {
+    console.log( 'Not called.' );
+  }, reason => {
+    console.error( 'onRejected function called: ', reason );
+  });
+ +

在所有其他情形,實現中的 Promise 被回傳。在以下例子中,第一個 then() 將回傳一個實現中包裹 42 的 promise,即使串接中的前一個 Promise 被否決。

+ +
Promise.reject()
+  .then( () => 99, () => 42 ) // onRejected returns 42 which is wrapped in a resolving Promise
+  .then( solution => console.log( 'Resolved with ' + solution ) ); // Resolved with 42
+ +

實務上,使用 catch 捕捉被否決的 promise 較理想的,而不建議使用兩個引數 then 語法,如下展示。

+ +
Promise.resolve()
+  .then( () => {
+    // Makes .then() return a rejected promise
+    throw 'Oh no!';
+  })
+  .catch( reason => {
+    console.error( 'onRejected function called: ', reason );
+  })
+  .then( () => {
+    console.log( "I am always called even if the prior then's promise rejects" );
+  });
+ +


+ 你也可以透過串接實作一個 Promise-based API 函式,基於它本身。

+ +
function fetch_current_data() {
+  // The fetch() API returns a Promise.  This function
+  // exposes a similar API, except the fulfillment
+  // value of this function's Promise has had more
+  // work done on it.
+  return fetch('current-data.json').then((response) => {
+    if (response.headers.get('content-type') != 'application/json') {
+      throw new TypeError();
+    }
+    var j = response.json();
+    // maybe do something with j
+    return j; // fulfillment value given to user of
+              // fetch_current_data().then()
+  });
+}
+
+ +

若 onFulfilled 回傳一個 promise,則 then 的實現/否決將取決它。

+ +
function resolveLater(resolve, reject) {
+  setTimeout(function () {
+    resolve(10);
+  }, 1000);
+}
+function rejectLater(resolve, reject) {
+  setTimeout(function () {
+    reject(20);
+  }, 1000);
+}
+
+var p1 = Promise.resolve('foo');
+var p2 = p1.then(function() {
+  // Return promise here, that will be resolved to 10 after 1 second
+  return new Promise(resolveLater);
+});
+p2.then(function(v) {
+  console.log('resolved', v);  // "resolved", 10
+}, function(e) {
+  // not called
+  console.log('rejected', e);
+});
+
+var p3 = p1.then(function() {
+  // Return promise here, that will be rejected with 20 after 1 second
+  return new Promise(rejectLater);
+});
+p3.then(function(v) {
+  // not called
+  console.log('resolved', v);
+}, function(e) {
+  console.log('rejected', e); // "rejected", 20
+});
+
+ +

規範

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-promise.prototype.then', 'Promise.prototype.then')}}{{Spec2('ES2015')}}Initial definition in an ECMA standard.
{{SpecName('ESDraft', '#sec-promise.prototype.then', 'Promise.prototype.then')}}{{Spec2('ESDraft')}} 
+ +

瀏覽器相容性

+ + + +

{{Compat("javascript/promise","Promise.prototype.then")}}

+ +

參見

+ + -- cgit v1.2.3-54-g00ecf