diff options
author | ian7525 <ian7525@gmail.com> | 2021-05-10 00:35:59 +0800 |
---|---|---|
committer | Irvin <irvinfly@gmail.com> | 2021-05-15 15:14:16 +0800 |
commit | b5165490983324e64bd3ca11b1b60151cfc1f134 (patch) | |
tree | 20118fbd0ab9487d77035a3b96b111e58d05004a /files | |
parent | 4a497b310a40ba465e2923826b0b092d6b81181f (diff) | |
download | translated-content-b5165490983324e64bd3ca11b1b60151cfc1f134.tar.gz translated-content-b5165490983324e64bd3ca11b1b60151cfc1f134.tar.bz2 translated-content-b5165490983324e64bd3ca11b1b60151cfc1f134.zip |
Update /learn/javascript/asynchronous/introducing/index.html file, zh-TW
Diffstat (limited to 'files')
-rw-r--r-- | files/zh-tw/learn/javascript/asynchronous/introducing/index.html | 164 |
1 files changed, 82 insertions, 82 deletions
diff --git a/files/zh-tw/learn/javascript/asynchronous/introducing/index.html b/files/zh-tw/learn/javascript/asynchronous/introducing/index.html index adaf89c906..3616cb089a 100644 --- a/files/zh-tw/learn/javascript/asynchronous/introducing/index.html +++ b/files/zh-tw/learn/javascript/asynchronous/introducing/index.html @@ -18,98 +18,98 @@ tags: <div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</div> -<p class="summary">在本篇文章中我們會先簡短的回顧我們在同步的 JavaScript 中所遭遇到的問題,並預先看看稍後將會使用哪些非同步的 JavaScript 技巧來解決此問題。</p> +<p class="summary">在本篇文章中我們會先簡短回顧在同步的 JavaScript 中所遭遇到的問題,並預先看看往後將會使用哪些非同步的 JavaScript 技巧來解決此問題。</p> <table class="learn-box standard-table"> <tbody> <tr> - <th scope="row">Prerequisites:</th> - <td>Basic computer literacy, a reasonable understanding of JavaScript fundamentals.</td> + <th scope="row">先備知識:</th> + <td>基本的電腦概念,理解 JavaScript 的基本原理。</td> </tr> <tr> - <th scope="row">Objective:</th> - <td>To gain familiarity with what asynchronous JavaScript is, how it differs from synchronous JavaScript, and what use cases it has.</td> + <th scope="row">學習目標:</th> + <td>熟悉什麼是非同步的 Javascript ,與同步的 Javascript 有甚麼差異,以及有哪些使用案例。</td> </tr> </tbody> </table> -<h2 id="Synchronous_JavaScript">Synchronous JavaScript</h2> +<h2 id="Synchronous_JavaScript">同步的 JavaScript</h2> -<p>To allow us to understand what <strong>{{Glossary("asynchronous")}}</strong> JavaScript is, we ought to start off by making sure we understand what <strong>{{Glossary("synchronous")}}</strong> JavaScript is. This section recaps some of the information we saw in the previous article.</p> +<p>在我們了解什麼是非同步( <strong>{{Glossary("asynchronous")}}</strong> ) JavaScript 之前,我們應該確保我們已經了解什麼是同步( <strong>{{Glossary("synchronous")}}</strong> ) JavaScript 。在本章節會回顧我們在前篇文章所看到的一些資訊。</p> -<p>A lot of the functionality we have looked at in previous learning area modules is synchronous — you run some code, and the result is returned as soon as the browser can do so. Let's look at a simple example (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html">see it live here</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html">see the source</a>):</p> +<p>我們在前一個學習單元所看到的大部分功能都是同步的——當跑一段程式碼,瀏覽器會將執行結果盡快的回傳。我們來看看一則簡單的範例(<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html">線上範例</a>,<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html">原始碼</a>):</p> <pre class="brush: js">const btn = document.querySelector('button'); btn.addEventListener('click', () => { - alert('You clicked me!'); + alert('你點擊了我!'); let pElem = document.createElement('p'); - pElem.textContent = 'This is a newly-added paragraph.'; + pElem.textContent = '這是一段新加的文字。'; document.body.appendChild(pElem); }); </pre> -<p>In this block, the lines are executed one after the other:</p> +<p>在這個程式區塊,指令是一行接著一行的執行:</p> <ol> - <li>We grab a reference to a {{htmlelement("button")}} element that is already available in the DOM.</li> - <li>We add a <code><a href="/en-US/docs/Web/API/Element/click_event">click</a></code> event listener to it so that when the button is clicked: + <li>我們先取得已經在 DOM 裡面的 {{htmlelement("button")}} 元素的參考。</li> + <li>我們加入一個 <code><a href="/zh-TW/docs/Web/API/Element/click_event">click</a></code> 事件監聽器,因此當按鈕被點擊時: <ol> - <li>An <code><a href="/en-US/docs/Web/API/Window/alert">alert()</a></code> message appears.</li> - <li>Once the alert is dismissed, we create a {{htmlelement("p")}} element.</li> - <li>We then give it some text content.</li> - <li>Finally, we append the paragraph to the document body.</li> + <li>彈出 <code><a href="/zh-TW/docs/Web/API/Window/alert">alert()</a></code> 訊息。</li> + <li>當關閉警告訊息後,我們新增一個 {{htmlelement("p")}} 元素。</li> + <li>給予一段文字內容。</li> + <li>最後,我們將文字段落嵌在文件本體( document body )上。</li> </ol> </li> </ol> -<p>While each operation is being processed, nothing else can happen — rendering is paused. This is because as we said in the <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">previous article</a>, <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts#javascript_is_single_threaded">JavaScript is single threaded</a>. Only one thing can happen at a time, on a single main thread, and everything else is blocked until an operation completes.</p> +<p>當正在執行每一個操作時,什麼事情都不會發生——渲染暫時停止。我們在<a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Introducing">上一篇文章</a>有提到,這是因為 <a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Concepts#javascript_is_single_threaded">Javascript 是跑在一條單執行緒</a>。主執行緒在同一時間只能做一件事情,直到目前操作完成為止其他的操作都會暫停。</p> -<p>So in the example above, after you've clicked the button the paragraph won't appear until after the OK button is pressed in the alert box. You can try it for yourself:</p> +<p>所以在上面的範例中,直到警告視窗的確認按鈕被按下為止之前,文字段落都不會出現。你可以試試看底下的範例:</p> <div class="hidden"> -<pre class="brush: html"><<span class="pl-ent">button</span>>Click me</<span class="pl-ent">button</span>></pre> +<pre class="brush: html"><<span class="pl-ent">button</span>>點擊我</<span class="pl-ent">button</span>></pre> </div> <p>{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}</p> <div class="notecard note"> -<p><strong>Note</strong>: It is important to remember that <code><a href="/en-US/docs/Web/API/Window/alert">alert()</a></code>, while being very useful for demonstrating a synchronous blocking operation, is terrible for use in real world applications.</p> +<p><strong>注意</strong>:使用 <code><a href="/zh-TW/docs/Web/API/Window/alert">alert()</a></code> 有個很重要的事情要記得,雖然用在證明是否為同步的阻塞操作非常有用,但非常不建議用在實際的應用程式上,使用體驗將會相當糟糕。</p> </div> -<h2 id="Asynchronous_JavaScript">Asynchronous JavaScript</h2> +<h2 id="Asynchronous_JavaScript">非同步 JavaScript</h2> -<p>For reasons illustrated earlier (e.g. related to blocking), many Web API features now use asynchronous code to run, especially those that access or fetch some kind of resource from an external device, such as fetching a file from the network, accessing a database and returning data from it, accessing a video stream from a web cam, or broadcasting the display to a VR headset.</p> +<p>如同先前所描述的原因(例如:和阻塞有關),現在許多 Web API 功能都是使用非同步程式碼的做法,特別是那些要從外部裝置存取或抓取某些種類資源的功能,像是從網路抓取檔案、存取資料庫並回傳資料、從網路攝影機取得視訊串流或者是將畫面透過廣播的方式顯示到 VR 頭盔等。</p> -<p>Why is this difficult to get to work using synchronous code? Let's look at a quick example. When you fetch an image from a server, you can't return the result immediately. That means that the following (pseudocode) wouldn't work:</p> +<p>為什麼同步的程式碼很難做到這些事?我們快速地看個例子。當你想要從伺服器抓取一張影像,你是沒有辦法馬上獲得結果的。這個意思是下面的程式碼(虛擬碼)是行不通的:</p> <pre class="brush: js">let response = fetch('myImage.png'); // fetch is asynchronous let blob = response.blob(); // display your image blob in the UI somehow</pre> -<p>That's because you don't know how long the image will take to download, so when you come to run the second line it will throw an error (possibly intermittently, possibly every time) because the <code>response</code> is not yet available. Instead, you need your code to wait until the <code>response</code> is returned before it tries to do anything else to it.</p> +<p>那是因為你不知道下載影像需要花上多少時間,所以當執行第二行時它將拋出一段錯誤(也許間歇性的發生,也許每一次都發生)這是因為 <code>response</code> 尚未取得結果還不能使用。因此在它嘗試做接下來的任何事之前,你需要讓你的程式碼先等到 <code>response</code> 回傳結果。</p> -<p>There are two main types of asynchronous code style you'll come across in JavaScript code, old-style callbacks and newer promise-style code. In the below sections we'll review each of these in turn.</p> +<p>你將會在 Javascript 程式碼碰到兩種主要類型的非同步程式碼風格,舊式的回呼風格(callback)以及新式的 promise 風格。在接下來的章節我們將會依次的檢視它們。</p> -<h2 id="Async_callbacks">Async callbacks</h2> +<h2 id="Async_callbacks">非同步回呼</h2> -<p>Async callbacks are functions that are specified as arguments when calling a function which will start executing code in the background. When the background code finishes running, it calls the callback function to let you know the work is done, or to let you know that something of interest has happened. Using callbacks is slightly old-fashioned now, but you'll still see them in use in a number of older-but-still-commonly-used APIs.</p> +<p>呼叫一個將在背景開始執行程式碼的函式,非同步回呼是作為該呼叫函式的引數( argument )的函式。當在背景環境執行的程式碼完成時,就會呼叫回呼函式( callback function )讓你知道工作已經結束或者是一些有趣的事情已經發生了。現在回呼似乎有點過時了,但你依然會在一些較舊但仍常被使用的 API 發現到這樣的寫法。</p> -<p>An example of an async callback is the second parameter of the {{domxref("EventTarget.addEventListener", "addEventListener()")}} method (as we saw in action above):</p> +<p>一個非同步回呼的例子就是作為在 {{domxref("EventTarget.addEventListener", "addEventListener()")}} 的第二個參數(正如我們在之前的例子看到的):</p> <pre class="brush: js">btn.addEventListener('click', () => { - alert('You clicked me!'); + alert('你點擊了我!'); let pElem = document.createElement('p'); - pElem.textContent = 'This is a newly-added paragraph.'; + pElem.textContent = '這是一段新加的文字。'; document.body.appendChild(pElem); });</pre> -<p>The first parameter is the type of event to be listened for, and the second parameter is a callback function that is invoked when the event is fired.</p> +<p>第一個參數是要被監聽的事件類型,第二個參數是當事件被觸發時會呼叫的回呼函式。</p> -<p>When we pass a callback function as an argument to another function, we are only passing the function's reference as an argument, i.e, the callback function is <strong>not</strong> executed immediately. It is “called back” (hence the name) asynchronously somewhere inside the containing function’s body. The containing function is responsible for executing the callback function when the time comes.</p> +<p>當我們將回呼函式做為一個引數給其他函式時,我們只傳送該回呼函式的參考做為引數,換句話說,回呼函式<strong>並非</strong>立即被執行。它將會在呼叫函式的內部某個地方非同步的「回去呼叫」它(因此稱回呼)。呼叫函式有責任的在適當的時機去執行該回呼函式。</p> -<p>You can write your own function containing a callback easily enough. Let's look at another example that loads a resource via the <a href="/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code> API</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">run it live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">see the source</a>):</p> +<p>自己寫一個包含回呼的呼叫函式很容易。我們來看看另一個從 <a href="/zh-TW/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a> API 載入資源的例子(<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">線上範例</a>,<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">原始碼</a>):</p> <pre class="brush: js">function loadAsset(url, type, callback) { let xhr = new XMLHttpRequest(); @@ -133,11 +133,11 @@ function displayImage(blob) { loadAsset('coffee.jpg', 'blob', displayImage);</pre> -<p>Here we create a <code>displayImage()</code> function that represents a blob passed to it as an object URL, then creates an image to display the URL in, appending it to the document's <code><body></code>. However, we then create a <code>loadAsset()</code> function that takes a callback as a parameter, along with a URL to fetch and a content type. It uses <code>XMLHttpRequest</code> (often abbreviated to "XHR") to fetch the resource at the given URL, then pass the response to the callback to do something with. In this case the callback is waiting on the XHR call to finish downloading the resource (using the <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code> event handler) before it passes it to the callback.</p> +<p>在這裡我們新增一個 <code>displayImage()</code> 函式,將 blob 做為一個參數傳進去函式來產生物件網址,然後建立一個可以用網址來顯示的影像,並將這個網址附加在 document 的 <code><body></code> 標籤內。然而,我們再新增一個 <code>loadAsset()</code> 函式,將回呼作為參數並伴隨抓取資源的網址以及內容型式傳進去函式。它使用 <code>XMLHttpRequest</code> (通常縮寫成「 XHR 」)根據網址去抓取資源,並將回傳結果傳送到回呼去做一些事情。在這個例子回呼正在等待 XHR 完成下載資源(使用 <code><a href="/zh-TW/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code> 事件處理器)後,再將資源傳遞給回呼。</p> -<p>Callbacks are versatile — not only do they allow you to control the order in which functions are run and what data is passed between them, they also allow you to pass data to different functions depending on circumstance. So you could have different actions to run on the response downloaded, such as <code>processJSON()</code>, <code>displayText()</code>, etc.</p> +<p>回呼是多樣性的——它不只可以讓你控制執行函式的呼叫順序以及在不同函式間傳遞的參數,還可以讓你根據情況將資料傳遞到不同的函式。所以你可以根據下載的回傳結果採取不同的處理方式,例如 <code>processJSON()</code> , <code>displayText()</code> 等等。</p> -<p>Note that not all callbacks are async — some run synchronously. An example is when we use {{jsxref("Array.prototype.forEach()")}} to loop through the items in an array (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html">see it live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html">the source</a>):</p> +<p>注意不是所有的回呼都是非同步的——有些是跑在同步上。有個例子是當我們使用 {{jsxref("Array.prototype.forEach()")}} 在陣列裡面用迴圈來遍歷每一個項目(<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html">線上範例</a>,<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html">原始碼</a>):</p> <pre class="brush: js">const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus']; @@ -145,11 +145,11 @@ gods.forEach(function (eachName, index){ console.log(index + '. ' + eachName); });</pre> -<p>In this example we loop through an array of Greek gods and print the index numbers and values to the console. The expected parameter of <code>forEach()</code> is a callback function, which itself takes two parameters, a reference to the array name and index values. However, it doesn't wait for anything — it runs immediately.</p> +<p>在這個例子我們用迴圈遍歷一個含有希臘諸神名稱的陣列並在控制台印出每一個索引和值。 <code>forEach()</code> 的預期參數是一個回呼函式,它有兩個參數代表陣列每個項目的名稱和索引。然而,它並未等待任何事情——它是立即的執行。</p> -<h2 id="Promises">Promises</h2> +<h2 id="Promises">Promise</h2> -<p>Promises are the new style of async code that you'll see used in modern Web APIs. A good example is the <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code> API, which is basically like a modern, more efficient version of {{domxref("XMLHttpRequest")}}. Let's look at a quick example, from our <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Fetching data from the server</a> article:</p> +<p>Promise 是作為非同步程式碼的一種新風格樣式,你將會在現代 Web API 看到這種用法。一個好例子是 <code><a href="/zh-TW/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code> API ,它基本上就像更新穎、更有效率版本的 {{domxref("XMLHttpRequest")}} 。我們藉由<a href="/zh-TW/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">從伺服器提取資料</a>這一篇文章快速地來看一個例子吧:</p> <pre class="brush: js">fetch('products.json').then(function(response) { return response.json(); @@ -161,42 +161,42 @@ gods.forEach(function (eachName, index){ });</pre> <div class="notecard note"> -<p><strong>Note</strong>: You can find the finished version on GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js">see the source here</a>, and also <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/">see it running live</a>).</p> +<p><strong>注意</strong>:你可以在 GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js">原始碼</a>,<a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/">線上範例</a>)找到最終版本。</p> </div> -<p>Here we see <code>fetch</code><code>()</code> taking a single parameter — the URL of a resource you want to fetch from the network — and returning a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a>. The promise is an object representing the completion or failure of the async operation. It represents an intermediate state, as it were. In essence, it's the browser's way of saying "I promise to get back to you with the answer as soon as I can," hence the name "promise."</p> +<p>在這裡我們看到 <code>fetch</code><code>()</code> 帶一個參數——你想要在網路上提取資源的網址——並回傳一個 <a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a> 。這一個 promise 用來表示一個完成或失敗的非同步操作的物件。它代表的是一種中間的狀態。本質上,它代表瀏覽器述說著:「我承諾我會盡快給予你一個答覆」,因此名稱就叫做「 promise 」。</p> -<p>This concept can take practice to get used to; it feels a little like {{interwiki("wikipedia", "Schrödinger's cat")}} in action. Neither of the possible outcomes have happened yet, so the fetch operation is currently waiting on the result of the browser trying to complete the operation at some point in the future. We've then got three further code blocks chained onto the end of the <code>fetch()</code>:</p> +<p>我們可以透過練習來習慣這個概念;在動作上它感覺有點像是 {{interwiki("wikipedia", "薛丁格的貓")}}。任何可能的結果已經發生,所以 fetch 指令正在等待瀏覽器在未來的某個時間點完成操作後並回傳的結果。我們接著在 <code>fetch()</code> 的結束會鏈結三個程式區塊:</p> <ul> - <li>Two <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code> blocks. Both contain a callback function that will run if the previous operation is successful, and each callback receives as input the result of the previous successful operation, so you can go forward and do something else to it. Each <code>.then()</code> block returns another promise, meaning that you can chain multiple <code>.then()</code> blocks onto each other, so multiple asynchronous operations can be made to run in order, one after another.</li> - <li>The <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">catch()</a></code> block at the end runs if any of the <code>.then()</code> blocks fail — in a similar way to synchronous <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> blocks, an error object is made available inside the <code>catch()</code>, which can be used to report the kind of error that has occurred. Note however that synchronous <code>try...catch</code> won't work with promises, although it will work with <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">async/await</a>, as you'll learn later on.</li> + <li>兩個 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code> 區塊。兩個都含有回呼函式且先前的操作成功時就會執行,每一個回呼函式都會收到上一個成功完成操作的結果,因此你可以繼續執行一些事情。每一個 <code>.then()</code> 區塊都會回傳另一個 promise ,代表你可以將多個 <code>.then()</code> 區塊彼此作連結,所以多個非同步操作可以一個接著一個被用來依序執行。</li> + <li>如果任何一個 <code>.then()</code> 區塊失敗就會跑到 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">catch()</a></code> 區塊——類似像在同步區塊內部的 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> 做法,在 <code>catch()</code> 內部會提供一個失敗的物件,可以用來報告是發生甚麼類型的錯誤。要注意到同步的 <code>try...catch</code> 不能與 promises 一起做使用,儘管它可以和 <a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Async_await">async / await</a> 待配使用,這稍後將會學習到。</li> </ul> <div class="notecard note"> -<p><strong>Note</strong>: You'll learn a lot more about promises later on in the module, so don't worry if you don't understand them fully yet.</p> +<p><strong>注意</strong>:你將會在稍後的單元學習到更多關於 promise 的觀念,即使現在尚未完全理解你也不需要太擔心。</p> </div> -<h3 id="The_event_queue">The event queue</h3> +<h3 id="The_event_queue">事件佇列</h3> -<p>Async operations like promises are put into an <strong>event queue</strong>, which runs after the main thread has finished processing so that they <em>do not block</em> subsequent JavaScript code from running. The queued operations will complete as soon as possible then return their results to the JavaScript environment.</p> +<p>像 promise 的非同步的操作被放進<strong>事件佇列</strong>中,佇列內的任務會在主執行緒完成它自己的工作後執行,所以它<strong>並不會阻擋</strong>後續 Javascript 程式碼的執行。在佇列內的操作會盡快完成並將結果回傳給 Javascript 環境。</p> -<h3 id="Promises_versus_callbacks">Promises versus callbacks</h3> +<h3 id="Promises_versus_callbacks">Promise 對上回呼</h3> -<p>Promises have some similarities to old-style callbacks. They are essentially a returned object to which you attach callback functions, rather than having to pass callbacks into a function.</p> +<p>Promise 和舊式的回呼有一些相似點。他們本質上都是回傳一個物件到回呼函式,而並非必須將回呼傳遞到呼叫函式。</p> -<p>However, promises are specifically made for handling async operations, and have many advantages over old-style callbacks:</p> +<p>然而 promise 更是專門設計用來處理非同步的操作,比起舊式的回呼有更多的優點:</p> <ul> - <li>You can chain multiple async operations together using multiple <code>.then()</code> operations, passing the result of one into the next one as an input. This is much harder to do with callbacks, which often ends up with a messy "pyramid of doom" (also known as <a href="http://callbackhell.com/">callback hell</a>).</li> - <li>Promise callbacks are always called in the strict order they are placed in the event queue.</li> - <li>Error handling is much better — all errors are handled by a single <code>.catch()</code> block at the end of the block, rather than being individually handled in each level of the "pyramid".</li> - <li>Promises avoid inversion of control, unlike old-style callbacks, which lose full control of how the function will be executed when passing a callback to a third-party library.</li> + <li>你可以使用 <code>.then()</code> 來鏈結多的非同步操作,將一個操作的結果作為下一個操作的輸入。這個對經常會導致「死亡金字塔」( pyramid of doom ,通常也被稱作為 <a href="http://callbackhell.com/">回呼地獄</a>)的回呼來說相當難辦到。</li> + <li>Promise 的執行順序總是依照放入事件佇列的順序來嚴格執行。</li> + <li>更佳的錯誤處理機制——所有的錯誤都在最後的 <code>.catch()</code> 區塊來統一處理,而不是在個別的區塊做處理。</li> + <li>Promise 避免失去控制權,不像舊式的回呼那樣傳送給第三方程式庫後就會無法控制回呼函式怎麼被執行。</li> </ul> -<h2 id="The_nature_of_asynchronous_code">The nature of asynchronous code</h2> +<h2 id="The_nature_of_asynchronous_code">非同步程式碼的天性</h2> -<p>Let's explore an example that further illustrates the nature of async code, showing what can happen when we are not fully aware of code execution order and the problems of trying to treat asynchronous code like synchronous code. The following example is fairly similar to what we've seen before (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html">see it live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">the source</a>). One difference is that we've included a number of {{domxref("console.log()")}} statements to illustrate an order that you might think the code would execute in.</p> +<p>我們來探索一個可以更進一步說明非同步程式碼天性的範例,並說明當我們無法充分了解程式碼的執行順序以及嘗試將非同步程式碼當作同步程式碼會發生什麼事。底下的範例和我們之前看到的相當相似( <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html">線上範例</a>,<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">原始碼</a>)。區別在於我們加入一些 {{domxref("console.log()")}} 來說明程式碼是否會依照你以為的順序來執行。</p> <pre class="brush: js">console.log ('Starting'); let image; @@ -215,11 +215,11 @@ fetch('coffee.jpg').then((response) => { console.log ('All done!');</pre> -<p>The browser will begin executing the code, see the first <code>console.log()</code> statement (<code>Starting</code>) and execute it, and then create the <code>image</code> variable.</p> +<p>瀏覽器將開始執行程式碼,看到第一行顯示 <code>Starting</code> 的 <code>console.log()</code> 並執行它,接著新增一個 <code>image</code> 變數。</p> -<p>It will then move to the next line and begin executing the <code>fetch()</code> block but, because <code>fetch()</code> executes asynchronously without blocking, code execution continues after the promise-related code, thereby reaching the final <code>console.log()</code> statement (<code>All done!</code>) and outputting it to the console.</p> +<p>接著它會移動至下一行並開始執行 <code>fetch()</code> 區塊,但是因為執行 <code>fetch()</code> 是非同步的且不會阻塞,所以程式碼會跳過 promise 相關的程式碼後繼續執行,因此到達最後<code>All done!</code> 的 <code>console.log()</code> 並顯示在控制台上。</p> -<p>Only once the <code>fetch()</code> block has completely finished running and delivering its result through the <code>.then()</code> blocks will we finally see the second <code>console.log()</code> message (<code>It worked :)</code>) appear. So the messages have appeared in a different order to what you might expect:</p> +<p>只有在完成 <code>fetch()</code> 並將回傳結果傳送至 <code>.then()</code> 之後,我們才會看到第二個 <code>console.log()</code> 顯示 <code>It worked :)</code> 的訊息出現。所以訊息的出現順序也許與你所期待的順序不同:</p> <ul> <li>Starting</li> @@ -227,7 +227,7 @@ console.log ('All done!');</pre> <li>It worked :)</li> </ul> -<p>If this confuses you, then consider the following smaller example:</p> +<p>如果上面的例子讓你感到混淆,那麼考慮一下下面更簡單的例子:</p> <pre class="brush: js">console.log("registering click handler"); @@ -237,51 +237,51 @@ button.addEventListener('click', () => { console.log("all done");</pre> -<p>This is very similar in behavior — the first and third <code>console.log()</code> messages will be shown immediately, but the second one is blocked from running until someone clicks the mouse button. The previous example works in the same way, except that in that case the second message is blocked on the promise chain fetching a resource then displaying it on screen, rather than a click.</p> +<p>這是一個非常相似的行為——第一個和第三個 <code>console.log()</code> 的訊息將會立即的顯示,但是第二個正在被阻塞直到有人點擊了滑鼠按鈕。和上一個例子運作的方式類似,除了之前的例子在第二步是因為要等待取得資源之後並顯示在螢幕上才會被阻塞住,而不是等待被點擊。</p> -<p>In a less trivial code example, this kind of setup could cause a problem — you can't include an async code block that returns a result, which you then rely on later in a sync code block. You just can't guarantee that the async function will return before the browser has processed the sync block.</p> +<p>在這個不直觀的例子中,這樣的設定方式可能會導致問題的發生——你不能在同步的程式碼去依賴一個非同步程式碼的執行結果,你不能保證非同步的函式會在瀏覽器執行下一個同步程式碼之前回傳結果。</p> -<p>To see this in action, try taking a local copy of <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">our example</a>, and changing the fourth <code>console.log()</code> call to the following:</p> +<p>為了看這個動作,試著在本地複製我們的<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">程式碼</a>,並將最後的 <code>console.log()</code> 的呼叫改成底下的方式:</p> <pre class="brush: js">console.log ('All done! ' + image.src + 'displayed.');</pre> -<p>You should now get an error in your console instead of the third message:</p> +<p>你應該會在控制台收到一個錯誤的訊息:</p> <pre><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body">TypeError: image is undefined; can't access its "src" property</span></span></span></pre> -<p>This is because at the time the browser tries to run the third <code>console.log()</code> statement, the <code>fetch()</code> block has not finished running so the <code>image</code> variable has not been given a value.</p> +<p>這是因為在這個時間點瀏覽器試著去執行最後的 <code>console.log()</code> 時 <code>fetch()</code> 還沒有完成執行,所以 <code>image</code> 變數尚未賦予值因而導致錯誤。</p> <div class="notecard note"> -<p><strong>Note</strong>: For security reasons, you can't <code>fetch()</code> files from your local filesystem (or run other such operations locally); to run the above example locally you'll have to run the example through a <a href="/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server">local webserver</a>.</p> +<p><strong>注意</strong>:由於安全性考量,你沒辦法呼叫 <code>fetch()</code> 從你的本地檔案系統抓取資料(或者其他在本地的相關操作)如果要在本地執行上面的範例,你需要在本地架起一個<a href="/zh-TW/docs/Learn/Common_questions/set_up_a_local_testing_server">網路伺服器</a>來執行。</p> </div> -<h2 id="Active_learning_make_it_all_async!">Active learning: make it all async!</h2> +<h2 id="Active_learning_make_it_all_async!">主動學習:讓一切非同步化!</h2> -<p>To fix the problematic <code>fetch()</code> example and make the three <code>console.log()</code> statements appear in the desired order, you could make the third <code>console.log()</code> statement run async as well. This can be done by moving it inside another <code>.then()</code> block chained onto the end of the second one, or by moving it inside the second <code>then()</code> block. Try fixing this now.</p> +<p>為了修復 <code>fetch()</code> 這個有問題的範例讓三個 <code>console.log()</code> 的敘述可以依序被執行你可以讓第三個 <code>console.log()</code> 也非同步的被執行。你可以新增一個新的 <code>.then()</code> 再將其放在裡面,這個新增的 <code>.then()</code> 再串連 promise 區塊的倒數第二個結尾;或者也可以將其放入原本的 <code>.then()</code> 中來解決這個問題。試著現在修復這個問題吧。</p> <div class="notecard note"> -<p><strong>Note</strong>: If you get stuck, you can <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html">find an answer here</a> (see it <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html">running live</a> also). You can also find a lot more information on promises in our <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a> guide, later on in the module.</p> +<p><strong>注意</strong>:如果你的想法卡住,你可以<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html">在這裡</a>找到解答(<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html">線上範例</a>)。你也可以在我們稍後的<a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Promises">優雅的使用 Promise 來處理非同步操作</a> 這個單元找到更多關於 promise 的資訊。</p> </div> -<h2 id="Conclusion">Conclusion</h2> +<h2 id="Conclusion">結論</h2> -<p>In its most basic form, JavaScript is a synchronous, blocking, single-threaded language, in which only one operation can be in progress at a time. But web browsers define functions and APIs that allow us to register functions that should not be executed synchronously, and should instead be invoked asynchronously when some kind of event occurs (the passage of time, the user's interaction with the mouse, or the arrival of data over the network, for example). This means that you can let your code do several things at the same time without stopping or blocking your main thread.</p> +<p>Javascript 基本上是一個同步性的、阻塞的,且是跑在單一執行緒的程式語言,也就是在同一時間只能執行一個操作。但是瀏覽器所定義的函式和 API 允許我們註冊一個不該被同步執行的函式,且這個函式應該在某些事件發生時需要非同步的被呼叫(到達指定的時間、使用者透過滑鼠互動,或者取得透過從網路所取到的資料)。這代表你可以讓你的程式碼在同時間做一些事情而不需暫停或阻塞你的主執行緒。</p> -<p>Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.</p> +<p>我們要讓程式碼同步地或非同步地執行取決於我們要做甚麼。</p> -<p>There are times when we want things to load and happen right away. For example when applying some user-defined styles to a webpage you'll want the styles to be applied as soon as possible.</p> +<p>有時候我們希望事情能夠立即的被載入並發生。例如某些使用者定義的樣式,你希望網頁能夠盡快地使用那些樣式。</p> -<p>If we're running an operation that takes time however, like querying a database and using the results to populate templates, it is better to push this off the main thread and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.</p> +<p>如果我們正在執行一些需要花一點時間的操作,就好比查詢資料庫並將結果填充到模板上,最好的方式是不要在主執行緒上執行並用非同步的方法來完成。隨著時間的學習,你將會了解到在更多的情況下,選擇使用非同步的技巧會比選擇同步的方式來的更合理。</p> <p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</p> -<h2 id="In_this_module">In this module</h2> +<h2 id="In_this_module">在本單元</h2> <ul> - <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> - <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> - <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> - <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> - <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> - <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> + <li><a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Concepts">非同步程式設計通用概念</a></li> + <li><a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Introducing">非同步的 JavaScript 介紹</a></li> + <li><a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">協同的非同步 JavaScript : Timeout 和 interval</a></li> + <li><a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Promises">優雅的使用 Promise 來處理非同步操作</a></li> + <li><a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Async_await">利用 async 及 await 讓非同步程式設計變得更容易</a></li> + <li><a href="/zh-TW/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">選擇正確的方法</a></li> </ul> |