-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduction: callbacks #101
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some suggestions based on our wiki
|
||
If there's any code below `loadScript(…)`, it doesn't wait until the script loading finishes. | ||
如果有任何代碼在 `loadScript(…)` 下方,它不會等到腳本載入完成後才執行。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果有任何代碼在 `loadScript(…)` 下方,它不會等到腳本載入完成後才執行。 | |
如果有任何程式碼在 `loadScript(…)` 下方,它不會等到腳本載入完成後才執行。 |
|
||
```js | ||
loadScript('/my/script.js'); | ||
// the code below loadScript | ||
// doesn't wait for the script loading to finish | ||
// 在 loadScript 下方的代碼,不會等待腳本載入完成才執行 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 在 loadScript 下方的代碼,不會等待腳本載入完成才執行 | |
// 在 loadScript 下方的程式碼,不會等待腳本載入完成才執行 |
|
||
But for multiple asynchronous actions that follow one after another we'll have code like this: | ||
但是對於多個非同步動作,一個接著一個,我們將會有像這樣的代碼: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
但是對於多個非同步動作,一個接著一個,我們將會有像這樣的代碼: | |
但是對於多個非同步動作,一個接著一個,我們將會有像這樣的程式碼: |
|
||
As calls become more nested, the code becomes deeper and increasingly more difficult to manage, especially if we have real code instead of `...` that may include more loops, conditional statements and so on. | ||
隨著呼叫的層次越多,代碼變得越來越深,同時也增加了維護的難度,尤其是實際的代碼中可能會有更多的迴圈、條件判斷等等。而不是像範例中的 `...` 。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
隨著呼叫的層次越多,代碼變得越來越深,同時也增加了維護的難度,尤其是實際的代碼中可能會有更多的迴圈、條件判斷等等。而不是像範例中的 `...` 。 | |
隨著呼叫的層次越多,程式碼變得越來越深,同時也增加了維護的難度,尤其是實際的程式碼中可能會有更多的迴圈、條件判斷等等。而不是像範例中的 `...` 。 |
|
||
It works, but the code looks like a torn apart spreadsheet. It's difficult to read, and you probably noticed that one needs to eye-jump between pieces while reading it. That's inconvenient, especially if the reader is not familiar with the code and doesn't know where to eye-jump. | ||
這能運作,但代碼看起來像被撕破的草稿。它很難閱讀,而且你大概也注意到了,讀者需要在閱讀時,在片段間做視線的跳躍。這很不方便,尤其是當讀者並不熟悉這段代碼,而且不曉得視線要跳到哪裡。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這能運作,但代碼看起來像被撕破的草稿。它很難閱讀,而且你大概也注意到了,讀者需要在閱讀時,在片段間做視線的跳躍。這很不方便,尤其是當讀者並不熟悉這段代碼,而且不曉得視線要跳到哪裡。 | |
這能運作,但程式碼看起來像被撕破的草稿。它很難閱讀,而且你大概也注意到了,讀者需要在閱讀時,在片段間做視線的跳躍。這很不方便,尤其是當讀者並不熟悉這段程式碼,且不曉得視線要跳到哪裡時。 |
|
||
Also, the functions named `step*` are all of single use, they are created only to avoid the "pyramid of doom." No one is going to reuse them outside of the action chain. So there's a bit of namespace cluttering here. | ||
而且,命名為 `step*` 的函式,全都只使用一次,它們被創造出來,只為了避免〝金字塔的詛咒〞。沒有任何一個函式會在動作鍊外,再被重新使用。因此這種方式有一點汙染了命名空間。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
而且,命名為 `step*` 的函式,全都只使用一次,它們被創造出來,只為了避免〝金字塔的詛咒〞。沒有任何一個函式會在動作鍊外,再被重新使用。因此這種方式有一點汙染了命名空間。 | |
此外,命名為 `step*` 的函式,全都只使用一次,它們被創造出來,只為了避免〝金字塔的詛咒〞。沒有任何一個函式會在動作鏈外,再被重新使用。因此這種方式有一點汙染了命名空間。 |
}); | ||
*/!* | ||
``` | ||
|
||
That's called a "callback-based" style of asynchronous programming. A function that does something asynchronously should provide a `callback` argument where we put the function to run after it's complete. | ||
這被稱為〝基於回呼〞風格的非同步編程。執行某些非同步動作的函式,應該要提供一個 `callback` 參數,讓我們能在非同步函式完成時,執行我們傳入的回呼。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這被稱為〝基於回呼〞風格的非同步編程。執行某些非同步動作的函式,應該要提供一個 `callback` 參數,讓我們能在非同步函式完成時,執行我們傳入的回呼。 | |
這被稱為〝基於回呼〞風格的非同步程式設計。執行某些非同步動作的函式,應該要提供一個 `callback` 參數,讓我們能在非同步函式完成時,執行我們傳入的回呼。 |
|
||
From the first look, it's a viable way of asynchronous coding. And indeed it is. For one or maybe two nested calls it looks fine. | ||
第一眼看來,對於非同步編程來說,上述的方式是可行的。而它確實也是可行的。對於一到二層的巢狀呼叫來說,看起來還不錯。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
第一眼看來,對於非同步編程來說,上述的方式是可行的。而它確實也是可行的。對於一到二層的巢狀呼叫來說,看起來還不錯。 | |
第一眼看來,對於非同步程式設計來說,上述的方式是可行的。而它確實也是可行的。對於一到二層的巢狀呼叫來說,看起來還不錯。 |
1. We load `1.js`, then if there's no error. | ||
2. We load `2.js`, then if there's no error. | ||
3. We load `3.js`, then if there's no error -- do something else `(*)`. | ||
上述代碼中: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
上述代碼中: | |
上述程式碼中: |
|
||
So this way of coding isn't very good. | ||
因此這樣的編碼方式並不夠好。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
因此這樣的編碼方式並不夠好。 | |
因此這樣的程式撰寫方式並不夠好。 |
all suggested words were be corrected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Thank you so much 🙇
I'll ask other reviewers to take one more look, and we'll be good to go.
|
||
Although, we'll try to make things clear anyway. There won't be anything really complex browser-wise. | ||
我們會試著讓事情保持單純。不會有任何瀏覽器方面的複雜事物。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我們會試著讓事情保持單純。不會有任何瀏覽器方面的複雜事物。 | |
儘管如此,我們還是會試著讓事情保持單純。不會有任何瀏覽器方面的複雜事物。 |
|
||
```js | ||
function loadScript(src) { | ||
// creates a <script> tag and append it to the page | ||
// this causes the script with given src to start loading and run when complete | ||
// 建立一個 <script> 標記,然後將它加到頁面上 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 建立一個 <script> 標記,然後將它加到頁面上 | |
// 建立一個 <script> 標籤,然後將它加到頁面上 |
let script = document.createElement('script'); | ||
script.src = src; | ||
document.head.append(script); | ||
} | ||
``` | ||
|
||
It appends to the document the new, dynamically created, tag `<script src="…">` with given `src`. The browser automatically starts loading it and executes when complete. | ||
這新的、動態生成的標記 `<script src="…">` 加到文件中。瀏覽器自動地開始載入它,並在載入完成後執行它。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這新的、動態生成的標記 `<script src="…">` 加到文件中。瀏覽器自動地開始載入它,並在載入完成後執行它。 | |
這新的、動態生成的標籤 `<script src="…">` 將從給予的 `src` 加到文件中。瀏覽器自動地開始載入它,並在載入完成後執行它。 |
loadScript('/my/script.js'); | ||
``` | ||
|
||
The script is executed "asynchronously", as it starts loading now, but runs later, when the function has already finished. | ||
腳本以〝非同步〞的方式被執行,因為它現在開始被載入,但之後才會執行。要注意的是在載入開始,到腳本執行之前,這個函式已經執行完畢了。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
腳本以〝非同步〞的方式被執行,因為它現在開始被載入,但之後才會執行。要注意的是在載入開始,到腳本執行之前,這個函式已經執行完畢了。 | |
腳本以〝非同步〞的方式被執行,因為它現在開始被載入,但在函式已結束之後才會執行。。 |
// ... | ||
``` | ||
|
||
Let's say we need to use the new script as soon as it loads. It declares new functions, and we want to run them. | ||
假設我們想要在腳本載入完成後,馬上使用它。腳本宣告了新的函式,而我們想要執行它們。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
假設我們想要在腳本載入完成後,馬上使用它。腳本宣告了新的函式,而我們想要執行它們。 | |
倘若我們想要在腳本載入完成後馬上使用它。也就是腳本宣告了新的函式,而我們想要執行它們。 |
*/!* | ||
``` | ||
|
||
Naturally, the browser probably didn't have time to load the script. As of now, the `loadScript` function doesn't provide a way to track the load completion. The script loads and eventually runs, that's all. But we'd like to know when it happens, to use new functions and variables from that script. | ||
這是因為,瀏覽器沒有足夠的時間載入腳本。現在, `loadScript` 函式沒有提供某種方式來追蹤載入完成了沒。我們只能知道,腳本終究會載入,然後執行。但是我們想要在腳本載入完成後,使用來自該腳本的新函式及新變數。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這是因為,瀏覽器沒有足夠的時間載入腳本。現在, `loadScript` 函式沒有提供某種方式來追蹤載入完成了沒。我們只能知道,腳本終究會載入,然後執行。但是我們想要在腳本載入完成後,使用來自該腳本的新函式及新變數。 | |
顯然,瀏覽器應該沒有足夠的時間載入腳本。至此, `loadScript` 函式尚未提供方式來追蹤載入完成了沒。我們只知道,腳本終究會載入並執行。但我們希望知道完成的時機點,以便使用來自該腳本的新函式及新變數。 |
}); | ||
*/!* | ||
``` | ||
|
||
That's called a "callback-based" style of asynchronous programming. A function that does something asynchronously should provide a `callback` argument where we put the function to run after it's complete. | ||
這被稱為〝基於回呼〞風格的非同步程式設計。執行某些非同步動作的函式,應該要提供一個 `callback` 參數,讓我們能在非同步函式完成時,執行我們傳入的回呼。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這被稱為〝基於回呼〞風格的非同步程式設計。執行某些非同步動作的函式,應該要提供一個 `callback` 參數,讓我們能在非同步函式完成時,執行我們傳入的回呼。 | |
這被稱為〝基於回呼(callback-based)〞風格的非同步程式設計。執行某些非同步動作的函式,應該要提供一個 `callback` 引數,讓我們能在非同步函式完成時,執行我們傳入的回呼。 |
|
||
What if we want one more script...? | ||
如果我們想在多一個腳本呢‧‧‧? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果我們想在多一個腳本呢‧‧‧? | |
如果我們想再多一個腳本呢‧‧‧? |
@@ -151,13 +150,13 @@ loadScript('/my/script.js', function(script) { | |||
}); | |||
``` | |||
|
|||
So, every new action is inside a callback. That's fine for few actions, but not good for many, so we'll see other variants soon. | |||
所以,每一個新動作都在一個回呼內。在只有少數動作的情況下,這是沒問題的。但如果有很多動作的話,那就不好了。我們很快會看到其它變型。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
所以,每一個新動作都在一個回呼內。在只有少數動作的情況下,這是沒問題的。但如果有很多動作的話,那就不好了。我們很快會看到其它變型。 | |
所以,每一個新動作都在一個回呼內。在只有少數動作的情況下還好。但如果有很多動作的話,那就不好了。我們很快會看到其它變型。 |
} | ||
}); | ||
``` | ||
|
||
Once again, the recipe that we used for `loadScript` is actually quite common. It's called the "error-first callback" style. | ||
再強調一次,我們使用在 `loadScript` 的處理方式,其實相當常見。它被稱為〝錯誤優先回呼〞的風格。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
再強調一次,我們使用在 `loadScript` 的處理方式,其實相當常見。它被稱為〝錯誤優先回呼〞的風格。 | |
再強調一次,我們使用在 `loadScript` 的處理方式,其實相當常見。它被稱為〝錯誤優先回呼(error-first callback)〞的風格。 |
1. `callback` 的第一個參數保留給錯誤,如果它有發生的話。然後呼叫 `callback(err)`。 | ||
2. 第二個參數(以及之後的其它參數)保留給成功的結果。然後呼叫 `callback(null, result1, result2…)`。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. `callback` 的第一個參數保留給錯誤,如果它有發生的話。然後呼叫 `callback(err)`。 | |
2. 第二個參數(以及之後的其它參數)保留給成功的結果。然後呼叫 `callback(null, result1, result2…)`。 | |
1. `callback` 的第一個引數保留給錯誤,如果它有發生的話。然後呼叫 `callback(err)`。 | |
2. 第二個引數(以及之後的其它引數)保留給成功的結果。然後呼叫 `callback(null, result1, result2…)`。 |
|
||
So the single `callback` function is used both for reporting errors and passing back results. | ||
所以單一的 `callback` 函式,被用於錯誤回報以及回傳結果。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
所以單一的 `callback` 函式,被用於錯誤回報以及回傳結果。 | |
所以單一的 `callback` 函式,被同時用於錯誤回報以及回傳結果。 |
|
||
From the first look, it's a viable way of asynchronous coding. And indeed it is. For one or maybe two nested calls it looks fine. | ||
第一眼看來,對於非同步程式設計來說,上述的方式是可行的。而它確實也是可行的。對於一到二層的巢狀呼叫來說,看起來還不錯。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
第一眼看來,對於非同步程式設計來說,上述的方式是可行的。而它確實也是可行的。對於一到二層的巢狀呼叫來說,看起來還不錯。 | |
第一眼看來,對於非同步程式設計來說,上述的方式是可行的。而它確實也是可行的。對於一到二層的巢狀呼叫來說,看起來還行。 |
|
||
But for multiple asynchronous actions that follow one after another we'll have code like this: | ||
但是對於多個非同步動作,一個接著一個,我們將會有像這樣的程式碼: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
但是對於多個非同步動作,一個接著一個,我們將會有像這樣的程式碼: | |
但是對於一個接著一個的多個非同步動作,我們將會有像這樣的程式碼: |
|
||
As calls become more nested, the code becomes deeper and increasingly more difficult to manage, especially if we have real code instead of `...` that may include more loops, conditional statements and so on. | ||
隨著呼叫的層次越多,程式碼變得越來越深,同時也增加了維護的難度,尤其是實際的程式碼中可能會有更多的迴圈、條件判斷等等。而不是像範例中的 `...` 。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
隨著呼叫的層次越多,程式碼變得越來越深,同時也增加了維護的難度,尤其是實際的程式碼中可能會有更多的迴圈、條件判斷等等。而不是像範例中的 `...` 。 | |
隨著呼叫的層次越多,程式碼變得越來越深,同時也增加了維護的難度,尤其是實際的程式碼中可能會有更多的迴圈、條件判斷等等。而不只是範例中的 `...` 。 |
|
||
That's sometimes called "callback hell" or "pyramid of doom." | ||
這有時候被稱為〝回呼地獄(callback hell)〞或〝金字塔的詛咒〞。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這有時候被稱為〝回呼地獄(callback hell)〞或〝金字塔的詛咒〞。 | |
這有時候被稱為〝回呼地獄(callback hell)〞或〝金字塔的詛咒(pyramid of doom)〞。 |
|
||
It works, but the code looks like a torn apart spreadsheet. It's difficult to read, and you probably noticed that one needs to eye-jump between pieces while reading it. That's inconvenient, especially if the reader is not familiar with the code and doesn't know where to eye-jump. | ||
這能運作,但程式碼看起來像被撕破的草稿。它很難閱讀,而且你大概也注意到了,讀者需要在閱讀時,在片段間做視線的跳躍。這很不方便,尤其是當讀者並不熟悉這段程式碼,而且不曉得視線要跳到哪裡。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這能運作,但程式碼看起來像被撕破的草稿。它很難閱讀,而且你大概也注意到了,讀者需要在閱讀時,在片段間做視線的跳躍。這很不方便,尤其是當讀者並不熟悉這段程式碼,而且不曉得視線要跳到哪裡。 | |
這雖然可行,但程式碼看起來像被撕破的草稿。它很難閱讀,而且你大概也注意到了,讀者需要在閱讀時,在片段間做視線的跳躍。這很不方便,尤其是當讀者並不熟悉這段程式碼,而且不曉得視線要跳到哪裡。 |
|
||
In the task <info:task/animate-circle> an animated growing circle is shown. | ||
在作業 <info:task/animate-circle> 中,成長的圈圈以動畫呈現。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在作業 <info:task/animate-circle> 中,成長的圈圈以動畫呈現。 | |
在課題 <info:task/animate-circle> 中,成長的圈圈以動畫呈現。 |
|
||
In the solution of the task, the function `showCircle(cx, cy, radius)` draws the circle, but gives no way to track when it's ready. | ||
在該項作業的解答中,函式 `showCircle(cx, cy, radius)` 畫了圈圈,但沒有提供追蹤它完成的方法。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在該項作業的解答中,函式 `showCircle(cx, cy, radius)` 畫了圈圈,但沒有提供追蹤它完成的方法。 | |
在該項課題的解答中,函式 `showCircle(cx, cy, radius)` 畫了圈圈,但沒有提供追蹤它完成的方法。 |
|
||
Add a callback argument: `showCircle(cx, cy, radius, callback)` to be called when the animation is complete. The `callback` should receive the circle `<div>` as an argument. | ||
增加一個回呼參數:`showCircle(cx, cy, radius, callback)` 讓它在動畫完成後被呼叫。 `callback` 應該要接收圈圈的 `<div>` 作為參數。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
增加一個回呼參數:`showCircle(cx, cy, radius, callback)` 讓它在動畫完成後被呼叫。 `callback` 應該要接收圈圈的 `<div>` 作為參數。 | |
增加一個回呼參數:`showCircle(cx, cy, radius, callback)` 讓它在動畫完成後被呼叫。 `callback` 應該要接收圈圈的 `<div>` 作為引數。 |
@@ -18,8 +18,8 @@ showCircle(150, 150, 100, div => { | |||
}); | |||
``` | |||
|
|||
Demo: | |||
範例: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
範例: | |
演示: |
|
||
[iframe src="solution" height=260] | ||
|
||
Take the solution of the task <info:task/animate-circle> as the base. | ||
將該作業的解答 <info:task/animate-circle> 當作基底。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
將該作業的解答 <info:task/animate-circle> 當作基底。 | |
將該課題的解答 <info:task/animate-circle> 當作基底。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LegendaryIn
Thanks for your contribution!
I've added some suggestions about the translations.
Please take a look and leave your preference.
Please make the requested changes. After it, add a comment "/done". |
/done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ArvinH I'm good with this PR, please feel free to merge it.
Thank you 💖 I updated the Progress Issue #1 🎉 🎉 🎉 |
Target chapter
1-js/11-async/1-callbacks
Modified files
article.md
01-animate-circle-callback/*