diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml
index c69c7025bb3a9f5..a1c71c39ac50f44 100644
--- a/.github/workflows/markdown-lint.yml
+++ b/.github/workflows/markdown-lint.yml
@@ -15,12 +15,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup Node.js environment
- uses: actions/setup-node@v2.5.1
+ uses: actions/setup-node@v3.0.0
with:
node-version: "12"
+ cache: yarn
- name: Lint markdown files
run: |
diff --git a/.github/workflows/pr-check_redirects.yml b/.github/workflows/pr-check_redirects.yml
index efc1026223e28b8..e69855c84063787 100644
--- a/.github/workflows/pr-check_redirects.yml
+++ b/.github/workflows/pr-check_redirects.yml
@@ -13,23 +13,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup Node.js environment
- uses: actions/setup-node@v2.5.1
+ uses: actions/setup-node@v3.0.0
with:
node-version: "12"
-
- - name: Cache node_modules
- uses: actions/cache@v2.1.7
- id: cached-node_modules
- with:
- path: |
- node_modules
- key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}-${{ hashFiles('.github/workflows/pr-check_redirects.yml') }}
+ cache: yarn
- name: Install all yarn packages
- if: steps.cached-node_modules.outputs.cache-hit != 'true'
run: |
yarn --frozen-lockfile
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
index 331ddc9b80370f3..31e78f82a62fa03 100644
--- a/.github/workflows/pr-labeler.yml
+++ b/.github/workflows/pr-labeler.yml
@@ -6,6 +6,6 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- - uses: actions/labeler@v3
+ - uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/pr-review-companion.yml b/.github/workflows/pr-review-companion.yml
index 7ef6472e42f809b..bbd409e10120823 100644
--- a/.github/workflows/pr-review-companion.yml
+++ b/.github/workflows/pr-review-companion.yml
@@ -57,13 +57,13 @@ jobs:
run: |
unzip build.zip -d build
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
repository: mdn/yari
path: yari
- name: Install Python
- uses: actions/setup-python@v2.3.2
+ uses: actions/setup-python@v3
with:
python-version: "3.8"
diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml
index cbd9015b9650f45..74bfa5340fa91ed 100644
--- a/.github/workflows/pr-test.yml
+++ b/.github/workflows/pr-test.yml
@@ -23,23 +23,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup Node.js environment
- uses: actions/setup-node@v2.5.1
+ uses: actions/setup-node@v3.0.0
with:
node-version: "12"
-
- - name: Cache node_modules
- uses: actions/cache@v2.1.7
- id: cached-node_modules
- with:
- path: |
- node_modules
- key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}-${{ hashFiles('.github/workflows/pr-test.yml') }}
+ cache: yarn
- name: Install all yarn packages
- if: steps.cached-node_modules.outputs.cache-hit != 'true'
run: |
yarn --frozen-lockfile
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index 16592a491120418..e01c48aa1484f01 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -12,23 +12,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup Node.js environment
- uses: actions/setup-node@v2.5.1
+ uses: actions/setup-node@v3.0.0
with:
node-version: "12"
-
- - name: Cache node_modules
- uses: actions/cache@v2.1.7
- id: cached-node_modules
- with:
- path: |
- node_modules
- key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}-${{ hashFiles('.github/workflows/preview.yml') }}
+ cache: yarn
- name: Install all yarn packages
- if: steps.cached-node_modules.outputs.cache-hit != 'true'
run: |
yarn --frozen-lockfile
diff --git a/files/en-us/_redirects.txt b/files/en-us/_redirects.txt
index 9f9f95baada4fbb..5c31a8c5cde6d2a 100644
--- a/files/en-us/_redirects.txt
+++ b/files/en-us/_redirects.txt
@@ -141,6 +141,7 @@
/en-US/docs/Advanced_styling_for_HTML_forms /en-US/docs/Learn/Forms/Advanced_form_styling
/en-US/docs/Alternative_style_sheets /en-US/docs/Web/CSS/Alternative_style_sheets
/en-US/docs/An_Overview_of_Accessible_Web_Applications_and_Widgets /en-US/docs/Web/Accessibility/An_overview_of_accessible_web_applications_and_widgets
+/en-US/docs/An_overview_of_NSS_Internals https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Animation /en-US/docs/Web/API/Animation
/en-US/docs/Animation/currentTime /en-US/docs/Web/API/Animation/currentTime
/en-US/docs/Animation/finish /en-US/docs/Web/API/Animation/finish
@@ -1918,8 +1919,8 @@
/en-US/docs/DOM/element.offsetLeft /en-US/docs/Web/API/HTMLElement/offsetLeft
/en-US/docs/DOM/element.offsetParent /en-US/docs/Web/API/HTMLElement/offsetParent
/en-US/docs/DOM/element.offsetWidth /en-US/docs/Web/API/HTMLElement/offsetWidth
-/en-US/docs/DOM/element.onafterscriptexecute /en-US/docs/Web/API/Document/onafterscriptexecute
-/en-US/docs/DOM/element.onbeforescriptexecute /en-US/docs/Web/API/Document/onbeforescriptexecute
+/en-US/docs/DOM/element.onafterscriptexecute /en-US/docs/Web/API/Document/afterscriptexecute_event
+/en-US/docs/DOM/element.onbeforescriptexecute /en-US/docs/Web/API/Document/beforescriptexecute_event
/en-US/docs/DOM/element.onblur /en-US/docs/Web/API/GlobalEventHandlers/onblur
/en-US/docs/DOM/element.onchange /en-US/docs/Web/API/GlobalEventHandlers/onchange
/en-US/docs/DOM/element.onclick /en-US/docs/Web/API/GlobalEventHandlers/onclick
@@ -3157,8 +3158,8 @@
/en-US/docs/Document_Object_Model_(DOM)/element.offsetLeft /en-US/docs/Web/API/HTMLElement/offsetLeft
/en-US/docs/Document_Object_Model_(DOM)/element.offsetParent /en-US/docs/Web/API/HTMLElement/offsetParent
/en-US/docs/Document_Object_Model_(DOM)/element.offsetWidth /en-US/docs/Web/API/HTMLElement/offsetWidth
-/en-US/docs/Document_Object_Model_(DOM)/element.onafterscriptexecute /en-US/docs/Web/API/Document/onafterscriptexecute
-/en-US/docs/Document_Object_Model_(DOM)/element.onbeforescriptexecute /en-US/docs/Web/API/Document/onbeforescriptexecute
+/en-US/docs/Document_Object_Model_(DOM)/element.onafterscriptexecute /en-US/docs/Web/API/Document/afterscriptexecute_event
+/en-US/docs/Document_Object_Model_(DOM)/element.onbeforescriptexecute /en-US/docs/Web/API/Document/beforescriptexecute_event
/en-US/docs/Document_Object_Model_(DOM)/element.onblur /en-US/docs/Web/API/GlobalEventHandlers/onblur
/en-US/docs/Document_Object_Model_(DOM)/element.onchange /en-US/docs/Web/API/GlobalEventHandlers/onchange
/en-US/docs/Document_Object_Model_(DOM)/element.onclick /en-US/docs/Web/API/GlobalEventHandlers/onclick
@@ -3588,6 +3589,7 @@
/en-US/docs/Games/Workflows/HTML5_Gamedev_Phaser_Device_Orientation /en-US/docs/Games/Tutorials/HTML5_Gamedev_Phaser_Device_Orientation
/en-US/docs/Games/Workflows/Touch_Event_Horizon /en-US/docs/Games/Tutorials/Touch_Event_Horizon
/en-US/docs/Games/visual_typescript_game_engine /en-US/docs/Games
+/en-US/docs/Getting_Started_With_NSS https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Getting_started_on_MDN /en-US/docs/MDN/Contribute/Getting_started
/en-US/docs/Glossary/AOM /en-US/docs/Glossary/Accessibility_tree
/en-US/docs/Glossary/B2G /en-US/docs/Glossary/Boot2Gecko
@@ -4022,11 +4024,9 @@
/en-US/docs/IndexedDB /en-US/docs/Web/API/IndexedDB_API
/en-US/docs/IndexedDB/Basic_Concepts_Behind_IndexedDB /en-US/docs/Web/API/IndexedDB_API/Basic_Terminology
/en-US/docs/IndexedDB/Cursor /en-US/docs/Web/API/IDBCursor
-/en-US/docs/IndexedDB/DatabaseException /en-US/docs/Web/API/IDBDatabaseException
/en-US/docs/IndexedDB/IDBCursor /en-US/docs/Web/API/IDBCursor
/en-US/docs/IndexedDB/IDBCursorWithValue /en-US/docs/Web/API/IDBCursorWithValue
/en-US/docs/IndexedDB/IDBDatabase /en-US/docs/Web/API/IDBDatabase
-/en-US/docs/IndexedDB/IDBDatabaseException /en-US/docs/Web/API/IDBDatabaseException
/en-US/docs/IndexedDB/IDBFactory /en-US/docs/Web/API/IDBFactory
/en-US/docs/IndexedDB/IDBIndex /en-US/docs/Web/API/IDBIndex
/en-US/docs/IndexedDB/IDBKeyRange /en-US/docs/Web/API/IDBKeyRange
@@ -5305,8 +5305,12 @@
/en-US/docs/Learn/How_to_create_an_HTML_document /en-US/docs/Learn/Getting_started_with_the_web
/en-US/docs/Learn/How_web_pages_work /en-US/docs/Learn/Common_questions/Pages_sites_servers_and_search_engines
/en-US/docs/Learn/Infrastructure /en-US/docs/Learn/Common_questions
-/en-US/docs/Learn/JavaScript/Asynchronous/Async_loops_and_intervals /en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals
-/en-US/docs/Learn/JavaScript/Asynchronous/Loops_and_intervals /en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals
+/en-US/docs/Learn/JavaScript/Asynchronous/Async_await /en-US/docs/Learn/JavaScript/Asynchronous/Promises
+/en-US/docs/Learn/JavaScript/Asynchronous/Async_loops_and_intervals /en-US/docs/Learn/JavaScript/Asynchronous
+/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach /en-US/docs/Learn/JavaScript/Asynchronous
+/en-US/docs/Learn/JavaScript/Asynchronous/Concepts /en-US/docs/Learn/JavaScript/Asynchronous/Introducing
+/en-US/docs/Learn/JavaScript/Asynchronous/Loops_and_intervals /en-US/docs/Learn/JavaScript/Asynchronous
+/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals /en-US/docs/Learn/JavaScript/Asynchronous
/en-US/docs/Learn/JavaScript/Asynchronous_JavaScript /en-US/docs/Learn/JavaScript/Asynchronous
/en-US/docs/Learn/JavaScript/Building_blocks/Functions/Build_your_own_function /en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function
/en-US/docs/Learn/JavaScript/Building_blocks/Functions/Return_values /en-US/docs/Learn/JavaScript/Building_blocks/Return_values
@@ -5481,6 +5485,7 @@
/en-US/docs/MDN/Contribute/Tools/KumaScript /en-US/docs/MDN/Tools/KumaScript
/en-US/docs/MDN/Contribute/Tools/KumaScript/Troubleshooting /en-US/docs/MDN/Tools/KumaScript/Troubleshooting
/en-US/docs/MDN/Contribute/Tools/Sample_server /en-US/docs/MDN/Tools/Sample_server
+/en-US/docs/MDN/Doc_status/NSPR https://firefox-source-docs.mozilla.org/nspr/index.html
/en-US/docs/MDN/Feedback /en-US/docs/MDN/Contribute/Feedback
/en-US/docs/MDN/Getting_started /en-US/docs/MDN/Contribute/Getting_started
/en-US/docs/MDN/Guidelines/CSS_style_guide /en-US/docs/MDN/Contribute/Markdown_in_MDN
@@ -5688,6 +5693,21 @@
/en-US/docs/Mozilla/Firefox/Releases/developers /en-US/docs/Mozilla/Firefox/Releases/63
/en-US/docs/Mozilla/MathML_Project/Fonts /en-US/docs/Web/MathML/Fonts
/en-US/docs/Mozilla/Performance/Scroll-linked_effects https://firefox-source-docs.mozilla.org/performance/scroll-linked_effects.html
+/en-US/docs/Mozilla/Projects/NSPR https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Creating_a_cookie_log https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/NSPR_build_instructions https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/Dynamic_Library_Linking https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/Hash_Tables https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/I_O_Functions https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/I_O_Types https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/Introduction_to_NSPR https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/Linked_Lists https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/Logging https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/NSPR_Error_Handling https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/NSPR_LOG_MODULES https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/NSPR_Types https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/PR_Write https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/Mozilla/Projects/NSPR/Reference/Threads https://firefox-source-docs.mozilla.org/nspr/index.html
/en-US/docs/Mozilla/Projects/NSS https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/An_overview_of_NSS_Internals https://firefox-source-docs.mozilla.org/security/nss/legacy/an_overview_of_nss_internals/index.html
/en-US/docs/Mozilla/Projects/NSS/Blank_Function https://firefox-source-docs.mozilla.org/security/nss/legacy/blank_function/index.html
@@ -5869,8 +5889,12 @@
/en-US/docs/Mozilla/Projects/NSS/NSS_3.64_release_notes https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_releases/nss_3.64_release_notes/index.html
/en-US/docs/Mozilla/Projects/NSS/NSS_3.65_release_notes https://firefox-source-docs.mozilla.org/security/nss/releases/nss_3_65.html
/en-US/docs/Mozilla/Projects/NSS/NSS_3.66_release_notes https://firefox-source-docs.mozilla.org/security/nss/releases/nss_3_66.html
+/en-US/docs/Mozilla/Projects/NSS/NSS_3.74_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/Mozilla/Projects/NSS/NSS_3.75_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/NSS_API_Guidelines https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_api_guidelines/index.html
+/en-US/docs/Mozilla/Projects/NSS/NSS_API_Guidelines/layer.gif https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/NSS_Config_Options https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_config_options/index.html
+/en-US/docs/Mozilla/Projects/NSS/NSS_Config_Options/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/NSS_Developer_Tutorial https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_developer_tutorial/index.html
/en-US/docs/Mozilla/Projects/NSS/NSS_Releases https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_releases/index.html
/en-US/docs/Mozilla/Projects/NSS/NSS_Sample_Code https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_sample_code/index.html
@@ -5915,6 +5939,7 @@
/en-US/docs/Mozilla/Projects/NSS/PKCS11/Module_Specs https://firefox-source-docs.mozilla.org/security/nss/legacy/pkcs11/module_specs/index.html
/en-US/docs/Mozilla/Projects/NSS/PKCS11_Functions https://firefox-source-docs.mozilla.org/security/nss/legacy/pkcs11_functions/index.html
/en-US/docs/Mozilla/Projects/NSS/PKCS11_Implement https://firefox-source-docs.mozilla.org/security/nss/legacy/pkcs11_implement/index.html
+/en-US/docs/Mozilla/Projects/NSS/PKCS11_Jar_Install https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/PKCS_12_functions https://firefox-source-docs.mozilla.org/security/nss/legacy/pkcs_12_functions/index.html
/en-US/docs/Mozilla/Projects/NSS/PKCS_7_functions https://firefox-source-docs.mozilla.org/security/nss/legacy/pkcs_7_functions/index.html
/en-US/docs/Mozilla/Projects/NSS/Python_binding_for_NSS https://firefox-source-docs.mozilla.org/security/nss/legacy/python_binding_for_nss/index.html
@@ -6006,7 +6031,9 @@
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_certutil https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__certutil/index.html
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_cmsutil https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__cmsutil/index.html
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_crlutil https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__crlutil/index.html
+/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_crlutil/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_modutil https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__modutil/index.html
+/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_modutil/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_pk12util https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__pk12util/index.html
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_ssltab https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__ssltab/index.html
/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_ssltap https://firefox-source-docs.mozilla.org/security/nss/legacy/reference/nss_tools__colon__ssltap/index.html
@@ -6019,6 +6046,8 @@
/en-US/docs/Mozilla/Projects/NSS/SSL_functions/pkfnc https://firefox-source-docs.mozilla.org/security/nss/legacy/ssl_functions/pkfnc/index.html
/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslcrt https://firefox-source-docs.mozilla.org/security/nss/legacy/ssl_functions/sslcrt/index.html
/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslerr https://firefox-source-docs.mozilla.org/security/nss/legacy/ssl_functions/sslerr/index.html
+/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslerr.html https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslerr/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslfnc https://firefox-source-docs.mozilla.org/security/nss/legacy/ssl_functions/sslfnc/index.html
/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslintro https://firefox-source-docs.mozilla.org/security/nss/legacy/ssl_functions/sslintro/index.html
/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslkey https://firefox-source-docs.mozilla.org/security/nss/legacy/ssl_functions/sslkey/index.html
@@ -6037,12 +6066,14 @@
/en-US/docs/Mozilla/Projects/NSS/Tools/vfyserv https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/vfyserv/index.html
/en-US/docs/Mozilla/Projects/NSS/Troubleshooting https://firefox-source-docs.mozilla.org/security/nss/legacy/troubleshooting/index.html
/en-US/docs/Mozilla/Projects/NSS/Utility_functions https://firefox-source-docs.mozilla.org/security/nss/legacy/utility_functions/index.html
+/en-US/docs/Mozilla/Projects/NSS/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/modutil-tasks.html https://firefox-source-docs.mozilla.org/security/nss/legacy/modutil-tasks.html/index.html
/en-US/docs/Mozilla/Projects/NSS/nss_sample_code/Encrypt_Decrypt_MAC_Using_Token https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_sample_code/encrypt_decrypt_mac_using_token/index.html
/en-US/docs/Mozilla/Projects/NSS/release_notes https://firefox-source-docs.mozilla.org/security/nss/legacy/nss_releases/index.html
/en-US/docs/Mozilla/Projects/NSS/tools https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/index.html
/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_certutil/index.html
/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil-tasks https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_certutil-tasks/index.html
+/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_cmsutil https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_cmsutil/index.html
/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_crlutil https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_crlutil/index.html
/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_dbck-tasks https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_dbck-tasks/index.html
@@ -6197,6 +6228,23 @@
/en-US/docs/NNTP /en-US/docs/Glossary/NNTP
/en-US/docs/NPAPI/Constants /en-US/docs/Glossary/Plugin
/en-US/docs/NPAPI:Constants /en-US/docs/Glossary/Plugin
+/en-US/docs/NSPR https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/NSPR/index.json https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/NSPR_API_Reference/Long_Long_(64-bit)_Integers https://firefox-source-docs.mozilla.org/nspr/index.html
+/en-US/docs/NSS https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.14.5_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.14_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.15.1_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.15.2_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.15.3_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.15.4_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_3.16_release_notes https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/NSS_Releases https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/Tools https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS/index.json https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS_Key_Log_Format https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS_Sources_Building_Testing https://firefox-source-docs.mozilla.org/security/nss/index.html
+/en-US/docs/NSS_reference/NSS_tools_:_certutil https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/NaN /en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN
/en-US/docs/Namespaces_in_IMSC /en-US/docs/Related/IMSC/Namespaces
/en-US/docs/Navigation_timing /en-US/docs/Web/API/Navigation_timing_API
@@ -6210,13 +6258,14 @@
/en-US/docs/Netscape_Gecko_User_Agent_Strings /en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
/en-US/docs/Node_server_without_framework /en-US/docs/Learn/Server-side/Node_server_without_framework
/en-US/docs/Notable_bugs_fixed_in_Firefox_3 /en-US/docs/Mozilla/Firefox/Releases/3/Notable_bugs_fixed
-/en-US/docs/Online/Offline_Events /en-US/docs/Web/API/Navigator/Online_and_offline_events
-/en-US/docs/Online_Offline_Events /en-US/docs/Web/API/Navigator/Online_and_offline_events
-/en-US/docs/Online_and_offline_events /en-US/docs/Web/API/Navigator/Online_and_offline_events
+/en-US/docs/Online/Offline_Events /en-US/docs/Web/API/Navigator/onLine
+/en-US/docs/Online_Offline_Events /en-US/docs/Web/API/Navigator/onLine
+/en-US/docs/Online_and_offline_events /en-US/docs/Web/API/Navigator/onLine
/en-US/docs/OpenWebApps /en-US/docs/Web/Progressive_web_apps
/en-US/docs/OpenWebDemos /en-US/docs/Web/Demos
/en-US/docs/Optimizing_Your_Pages_for_Speculative_Parsing /en-US/docs/Glossary/speculative_parsing
/en-US/docs/Other_JavaScript_tools /en-US/docs/Tools
+/en-US/docs/Overview_of_NSS https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/PHP /en-US/docs/Glossary/PHP
/en-US/docs/POP3 /en-US/docs/Glossary/POP
/en-US/docs/Parsing_and_serializing_XML /en-US/docs/Web/Guide/Parsing_and_serializing_XML
@@ -6260,6 +6309,7 @@
/en-US/docs/Property_compatibility_table_for_form_widgets /en-US/docs/Learn/Forms/Property_compatibility_table_for_form_controls
/en-US/docs/Python /en-US/docs/Learn/Server-side/Django
/en-US/docs/Python/Virtualenv https://github.com/mdn/archived-content/tree/main/files/en-us/mozilla/virtualenv
+/en-US/docs/Python_binding_for_NSS https://firefox-source-docs.mozilla.org/security/nss/index.html
/en-US/docs/Quirks_Mode_and_Standards_Mode /en-US/docs/Web/HTML/Quirks_Mode_and_Standards_Mode
/en-US/docs/Quirks_Mode_and_Standards_Mode/Quirks_Mode_and_Standards_Mode /en-US/docs/Web/HTML/Quirks_Mode_and_Standards_Mode
/en-US/docs/Quirks_Mode_and_Standards_Mode1/Quirks_Mode_and_Standards_Mode /en-US/docs/Web/HTML/Quirks_Mode_and_Standards_Mode
@@ -7202,7 +7252,7 @@
/en-US/docs/Web/API/AudioContext/decodeAudioData /en-US/docs/Web/API/BaseAudioContext/decodeAudioData
/en-US/docs/Web/API/AudioContext/destination /en-US/docs/Web/API/BaseAudioContext/destination
/en-US/docs/Web/API/AudioContext/listener /en-US/docs/Web/API/BaseAudioContext/listener
-/en-US/docs/Web/API/AudioContext/onstatechange /en-US/docs/Web/API/BaseAudioContext/onstatechange
+/en-US/docs/Web/API/AudioContext/onstatechange /en-US/docs//Web/API/BaseAudioContext/statechange_event
/en-US/docs/Web/API/AudioContext/sampleRate /en-US/docs/Web/API/BaseAudioContext/sampleRate
/en-US/docs/Web/API/AudioContext/state /en-US/docs/Web/API/BaseAudioContext/state
/en-US/docs/Web/API/AudioContext/suspend_event /en-US/docs/Web/API/HTMLMediaElement/suspend_event
@@ -7235,10 +7285,15 @@
/en-US/docs/Web/API/AudioParam.setValueCurveAtTime /en-US/docs/Web/API/AudioParam/setValueCurveAtTime
/en-US/docs/Web/API/AudioParam.value /en-US/docs/Web/API/AudioParam/value
/en-US/docs/Web/API/AudioScheduledSourceNode/onended /en-US/docs/Web/API/AudioScheduledSourceNode/ended_event
+/en-US/docs/Web/API/AudioTrackList/onaddtrack /en-US/docs/Web/API/AudioTrackList/addtrack_event
+/en-US/docs/Web/API/AudioTrackList/onchange /en-US/docs/Web/API/AudioTrackList/change_event
+/en-US/docs/Web/API/AudioTrackList/onremovetrack /en-US/docs/Web/API/AudioTrackList/removetrack_event
/en-US/docs/Web/API/AudioWorkletNode/AudioWorkletNode.parameters /en-US/docs/Web/API/AudioWorkletNode/parameters
+/en-US/docs/Web/API/AudioWorkletNode/onprocessorerror /en-US/docs/Web/API/AudioWorkletNode/processorerror_event
/en-US/docs/Web/API/AudioWorkletNodeOptions /en-US/docs/Web/API/AudioWorkletNode/AudioWorkletNode
/en-US/docs/Web/API/BackgroundFetchRegistration/onprogress /en-US/docs/Web/API/BackgroundFetchRegistration/progress_event
/en-US/docs/Web/API/Barcode_Detector_API /en-US/docs/Web/API/Barcode_Detection_API
+/en-US/docs/Web/API/BaseAudioContext/onstatechange /en-US/docs//Web/API/BaseAudioContext/statechange_event
/en-US/docs/Web/API/BaseAudioContext/resume /en-US/docs/Web/API/AudioContext/resume
/en-US/docs/Web/API/BatteryManager.charging /en-US/docs/Web/API/BatteryManager/charging
/en-US/docs/Web/API/BatteryManager.chargingTime /en-US/docs/Web/API/BatteryManager/chargingTime
@@ -7542,7 +7597,6 @@
/en-US/docs/Web/API/DataTransferItemList/DataTransferItem /en-US/docs/Web/API/DataTransferItemList
/en-US/docs/Web/API/DataTransferItemList/DataTransferItemList /en-US/docs/Web/API/DataTransferItemList
/en-US/docs/Web/API/DataView /en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
-/en-US/docs/Web/API/DatabaseException /en-US/docs/Web/API/IDBDatabaseException
/en-US/docs/Web/API/DedicatedWorkerGlobalScope.onmessage /en-US/docs/Web/API/DedicatedWorkerGlobalScope/onmessage
/en-US/docs/Web/API/DedicatedWorkerGlobalScope.postMessage /en-US/docs/Web/API/DedicatedWorkerGlobalScope/postMessage
/en-US/docs/Web/API/DelayNode.delayTime /en-US/docs/Web/API/DelayNode/delayTime
@@ -7602,6 +7656,8 @@
/en-US/docs/Web/API/Document/mozFullScreenEnabled /en-US/docs/Web/API/Document/fullscreenEnabled
/en-US/docs/Web/API/Document/namespaceURI /en-US/docs/Web/API/Element/namespaceURI
/en-US/docs/Web/API/Document/onabort /en-US/docs/Web/API/GlobalEventHandlers/onabort
+/en-US/docs/Web/API/Document/onafterscriptexecute /en-US/docs/Web/API/Document/afterscriptexecute_event
+/en-US/docs/Web/API/Document/onbeforescriptexecute /en-US/docs/Web/API/Document/beforescriptexecute_event
/en-US/docs/Web/API/Document/onblur /en-US/docs/Web/API/GlobalEventHandlers/onblur
/en-US/docs/Web/API/Document/onchange /en-US/docs/Web/API/GlobalEventHandlers/onchange
/en-US/docs/Web/API/Document/onclick /en-US/docs/Web/API/GlobalEventHandlers/onclick
@@ -7626,6 +7682,7 @@
/en-US/docs/Web/API/Document/onselect /en-US/docs/Web/API/GlobalEventHandlers/onselect
/en-US/docs/Web/API/Document/onselectionchange /en-US/docs/Web/API/GlobalEventHandlers/onselectionchange
/en-US/docs/Web/API/Document/onsubmit /en-US/docs/Web/API/GlobalEventHandlers/onsubmit
+/en-US/docs/Web/API/Document/onvisibilitychange /en-US/docs/Web/API/Document/visibilitychange_event
/en-US/docs/Web/API/Document/resourcetimingbufferfull_event /en-US/docs/Web/API/Performance/resourcetimingbufferfull_event
/en-US/docs/Web/API/Document/timeline/currentTime /en-US/docs/Web/API/AnimationTimeline/currentTime
/en-US/docs/Web/API/DocumentFragment.DocumentFragment /en-US/docs/Web/API/DocumentFragment/DocumentFragment
@@ -7804,6 +7861,9 @@
/en-US/docs/Web/API/FileReader.readAsText /en-US/docs/Web/API/FileReader/readAsText
/en-US/docs/Web/API/FileReader.readyState /en-US/docs/Web/API/FileReader/readyState
/en-US/docs/Web/API/FileReader.result /en-US/docs/Web/API/FileReader/result
+/en-US/docs/Web/API/FileReader/onabort /en-US/docs/Web/API/FileReader/abort_event
+/en-US/docs/Web/API/FileReader/onerror /en-US/docs/Web/API/FileReader/error_event
+/en-US/docs/Web/API/FileReader/onload /en-US/docs/Web/API/FileReader/load_event
/en-US/docs/Web/API/FileRequest.lockedFile /en-US/docs/Web/API/FileRequest/lockedFile
/en-US/docs/Web/API/FileRequest.onprogress /en-US/docs/Web/API/FileRequest/onprogress
/en-US/docs/Web/API/FileSystemFileEntry/FileSystemFileEntry.createWriter /en-US/docs/Web/API/FileSystemFileEntry/createWriter
@@ -7818,6 +7878,11 @@
/en-US/docs/Web/API/FocusEvent.FocusEvent /en-US/docs/Web/API/FocusEvent/FocusEvent
/en-US/docs/Web/API/FocusEvent.relatedTarget /en-US/docs/Web/API/FocusEvent/relatedTarget
/en-US/docs/Web/API/FontFace/FontFace.style /en-US/docs/Web/API/FontFace/style
+/en-US/docs/Web/API/FontFaceSet/loading_error /en-US/docs/Web/API/FontFaceSet/loading_event
+/en-US/docs/Web/API/FontFaceSet/loadingdone_error /en-US/docs/Web/API/FontFaceSet/loadingdone_event
+/en-US/docs/Web/API/FontFaceSet/onloading /en-US/docs/Web/API/FontFaceSet/loading_event
+/en-US/docs/Web/API/FontFaceSet/onloadingdone /en-US/docs/Web/API/FontFaceSet/loadingdone_event
+/en-US/docs/Web/API/FontFaceSet/onloadingerror /en-US/docs/Web/API/FontFaceSet/loadingerror_event
/en-US/docs/Web/API/FullscreenOptions /en-US/docs/Web/API/Element/requestFullScreen
/en-US/docs/Web/API/FullscreenOptions/navigationUI /en-US/docs/Web/API/Element/requestFullScreen
/en-US/docs/Web/API/GLbitfield /en-US/docs/Web/API/WebGL_API/Types
@@ -8216,7 +8281,6 @@
/en-US/docs/Web/API/Index /en-US/docs/Web/API
/en-US/docs/Web/API/IndexedDB_API/Basic_Concepts_Behind_IndexedDB /en-US/docs/Web/API/IndexedDB_API/Basic_Terminology
/en-US/docs/Web/API/IndexedDB_API/Cursor /en-US/docs/Web/API/IDBCursor
-/en-US/docs/Web/API/IndexedDB_API/DatabaseException /en-US/docs/Web/API/IDBDatabaseException
/en-US/docs/Web/API/IndexedDB_API/Index /en-US/docs/Web/API/IDBIndex
/en-US/docs/Web/API/IndexedDB_API/IndexedDB_primer /en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
/en-US/docs/Web/API/IndexedDB_API/KeyRange /en-US/docs/Web/API/IDBKeyRange
@@ -8298,6 +8362,8 @@
/en-US/docs/Web/API/MediaCapabilitiesInfo /en-US/docs/Web/API/MediaCapabilities/encodingInfo
/en-US/docs/Web/API/MediaCapabilities_API /en-US/docs/Web/API/Media_Capabilities_API/Using_the_Media_Capabilities_API
/en-US/docs/Web/API/MediaDevices/mediaDevices.getUserMedia /en-US/docs/Web/API/MediaDevices/getUserMedia
+/en-US/docs/Web/API/MediaKeySession/onkeystatuseschange /en-US/docs/Web/API/MediaKeySession/keystatuseschange_event
+/en-US/docs/Web/API/MediaKeySession/onmessage /en-US/docs/Web/API/MediaKeySession/message_event
/en-US/docs/Web/API/MediaKeySystemConfiguration /en-US/docs/Web/API/MediaKeySystemAccess/getConfiguration
/en-US/docs/Web/API/MediaKeySystemConfiguration/audioCapabilities /en-US/docs/Web/API/MediaKeySystemAccess/getConfiguration
/en-US/docs/Web/API/MediaKeySystemConfiguration/distinctiveIdentifier /en-US/docs/Web/API/MediaKeySystemAccess/getConfiguration
@@ -8456,6 +8522,7 @@
/en-US/docs/Web/API/Navigator.vendor /en-US/docs/Web/API/Navigator/vendor
/en-US/docs/Web/API/Navigator.vendorSub /en-US/docs/Web/API/Navigator/vendorSub
/en-US/docs/Web/API/Navigator.vibrate /en-US/docs/Web/API/Navigator/vibrate
+/en-US/docs/Web/API/Navigator/Online_and_offline_events /en-US/docs/Web/API/Navigator/onLine
/en-US/docs/Web/API/Navigator/getVRDevices /en-US/docs/Web/API/Navigator/getVRDisplays
/en-US/docs/Web/API/Navigator/mediaDevices.getUserMedia /en-US/docs/Web/API/MediaDevices/getUserMedia
/en-US/docs/Web/API/Navigator/mediaDevices/enumerateDevices /en-US/docs/Web/API/MediaDevices/enumerateDevices
@@ -8488,7 +8555,7 @@
/en-US/docs/Web/API/NavigatorLanguage/languages /en-US/docs/Web/API/Navigator/languages
/en-US/docs/Web/API/NavigatorOnLine /en-US/docs/Web/API/Navigator
/en-US/docs/Web/API/NavigatorOnLine.onLine /en-US/docs/Web/API/Navigator/onLine
-/en-US/docs/Web/API/NavigatorOnLine/Online_and_offline_events /en-US/docs/Web/API/Navigator/Online_and_offline_events
+/en-US/docs/Web/API/NavigatorOnLine/Online_and_offline_events /en-US/docs/Web/API/Navigator/onLine
/en-US/docs/Web/API/NavigatorOnLine/onLine /en-US/docs/Web/API/Navigator/onLine
/en-US/docs/Web/API/NavigatorPlugins /en-US/docs/Web/API/Navigator
/en-US/docs/Web/API/NavigatorPlugins.javaEnabled /en-US/docs/Web/API/Navigator/javaEnabled
@@ -8580,10 +8647,11 @@
/en-US/docs/Web/API/NotificationEvent/NotificationEvent() /en-US/docs/Web/API/NotificationEvent/NotificationEvent
/en-US/docs/Web/API/Notifications_API/Using_the_Web_Notifications_API /en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
/en-US/docs/Web/API/ObjectStore /en-US/docs/Web/API/IDBObjectStore
-/en-US/docs/Web/API/OfflineAudioContext.oncomplete /en-US/docs/Web/API/OfflineAudioContext/oncomplete
+/en-US/docs/Web/API/OfflineAudioContext.oncomplete /en-US/docs/Web/API/OfflineAudioContext/complete_event
/en-US/docs/Web/API/OfflineAudioContext.startRendering /en-US/docs/Web/API/OfflineAudioContext/startRendering
/en-US/docs/Web/API/OfflineAudioContext.startRendering_(promise) /en-US/docs/Web/API/OfflineAudioContext/startRendering
/en-US/docs/Web/API/OfflineAudioContext/complete /en-US/docs/Web/API/OfflineAudioContext/complete_event
+/en-US/docs/Web/API/OfflineAudioContext/oncomplete /en-US/docs/Web/API/OfflineAudioContext/complete_event
/en-US/docs/Web/API/OfflineAudioContext/startRendering(promise) /en-US/docs/Web/API/OfflineAudioContext/startRendering
/en-US/docs/Web/API/OffscreenCanvas/OffscreenCanvas.convertToBlob() /en-US/docs/Web/API/OffscreenCanvas/convertToBlob
/en-US/docs/Web/API/OffscreenCanvas/toBlob /en-US/docs/Web/API/OffscreenCanvas/convertToBlob
@@ -8649,6 +8717,7 @@
/en-US/docs/Web/API/Performance.now /en-US/docs/Web/API/Performance/now
/en-US/docs/Web/API/Performance.now() /en-US/docs/Web/API/Performance/now
/en-US/docs/Web/API/Performance.timing /en-US/docs/Web/API/Performance/timing
+/en-US/docs/Web/API/Performance/onresourcetimingbufferfull /en-US/docs/Web/API/Performance/resourcetimingbufferfull_event
/en-US/docs/Web/API/PerformanceEntry/connectEnd /en-US/docs/Web/API/PerformanceResourceTiming/connectEnd
/en-US/docs/Web/API/PerformanceEntry/connectStart /en-US/docs/Web/API/PerformanceResourceTiming/connectStart
/en-US/docs/Web/API/PerformanceEntry/decodedBodySize /en-US/docs/Web/API/PerformanceResourceTiming/decodedBodySize
@@ -8719,6 +8788,7 @@
/en-US/docs/Web/API/PositionOptions/maximumAge /en-US/docs/Web/API/Geolocation/getCurrentPosition
/en-US/docs/Web/API/PositionOptions/timeout /en-US/docs/Web/API/Geolocation/getCurrentPosition
/en-US/docs/Web/API/PositionSensorVRDevice/getState() /en-US/docs/Web/API/PositionSensorVRDevice/getState
+/en-US/docs/Web/API/PresentationAvailability/onchange /en-US/docs/Web/API/PresentationAvailability
/en-US/docs/Web/API/PresentationConnectionClosedEvent /en-US/docs/Web/API/PresentationConnectionCloseEvent
/en-US/docs/Web/API/ProgressEvent.ProgressEvent /en-US/docs/Web/API/ProgressEvent/ProgressEvent
/en-US/docs/Web/API/ProgressEvent.initProgressEvent /en-US/docs/Web/API/ProgressEvent/initProgressEvent
@@ -8994,6 +9064,7 @@
/en-US/docs/Web/API/ServiceWorker_API/Using_Service_Workers:_The_Basics /en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
/en-US/docs/Web/API/SharedWorker.SharedWorker /en-US/docs/Web/API/SharedWorker/SharedWorker
/en-US/docs/Web/API/SharedWorker.port /en-US/docs/Web/API/SharedWorker/port
+/en-US/docs/Web/API/SharedWorker/onerror /en-US/docs/Web/API/SharedWorker/error_event
/en-US/docs/Web/API/SharedWorkerGlobalScope.applicationCache /en-US/docs/Web/API/SharedWorkerGlobalScope/applicationCache
/en-US/docs/Web/API/SharedWorkerGlobalScope.name /en-US/docs/Web/API/SharedWorkerGlobalScope/name
/en-US/docs/Web/API/SharedWorkerGlobalScope.onconnect /en-US/docs/Web/API/SharedWorkerGlobalScope/onconnect
@@ -9369,6 +9440,7 @@
/en-US/docs/Web/API/Window/mozRequestAnimationFrame /en-US/docs/Web/API/window/requestAnimationFrame
/en-US/docs/Web/API/Window/onabort /en-US/docs/Web/API/GlobalEventHandlers/onabort
/en-US/docs/Web/API/Window/onafterprint /en-US/docs/Web/API/WindowEventHandlers/onafterprint
+/en-US/docs/Web/API/Window/onappinstalled /en-US/docs/Web/API/Window/appinstalled_event
/en-US/docs/Web/API/Window/onbeforeprint /en-US/docs/Web/API/WindowEventHandlers/onbeforeprint
/en-US/docs/Web/API/Window/onbeforeunload /en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
/en-US/docs/Web/API/Window/onblur /en-US/docs/Web/API/GlobalEventHandlers/onblur
@@ -9382,7 +9454,7 @@
/en-US/docs/Web/API/Window/ongamepaddisconnected /en-US/docs/Web/API/Window/gamepaddisconnected_event
/en-US/docs/Web/API/Window/onhashchange /en-US/docs/Web/API/WindowEventHandlers/onhashchange
/en-US/docs/Web/API/Window/oninput /en-US/docs/Web/API/GlobalEventHandlers/onkeydown
-/en-US/docs/Web/API/Window/oninstall /en-US/docs/Web/API/Window/onappinstalled
+/en-US/docs/Web/API/Window/oninstall /en-US/docs/Web/API/Window/appinstalled_event
/en-US/docs/Web/API/Window/onkeydown /en-US/docs/Web/API/GlobalEventHandlers/onkeydown
/en-US/docs/Web/API/Window/onkeypress /en-US/docs/Web/API/GlobalEventHandlers/onkeypress
/en-US/docs/Web/API/Window/onkeyup /en-US/docs/Web/API/GlobalEventHandlers/onkeyup
@@ -9702,8 +9774,8 @@
/en-US/docs/Web/API/element.offsetLeft /en-US/docs/Web/API/HTMLElement/offsetLeft
/en-US/docs/Web/API/element.offsetParent /en-US/docs/Web/API/HTMLElement/offsetParent
/en-US/docs/Web/API/element.offsetWidth /en-US/docs/Web/API/HTMLElement/offsetWidth
-/en-US/docs/Web/API/element.onafterscriptexecute /en-US/docs/Web/API/Document/onafterscriptexecute
-/en-US/docs/Web/API/element.onbeforescriptexecute /en-US/docs/Web/API/Document/onbeforescriptexecute
+/en-US/docs/Web/API/element.onafterscriptexecute /en-US/docs/Web/API/Document/afterscriptexecute_event
+/en-US/docs/Web/API/element.onbeforescriptexecute /en-US/docs/Web/API/Document/beforescriptexecute_event
/en-US/docs/Web/API/element.onblur /en-US/docs/Web/API/GlobalEventHandlers/onblur
/en-US/docs/Web/API/element.onchange /en-US/docs/Web/API/GlobalEventHandlers/onchange
/en-US/docs/Web/API/element.onclick /en-US/docs/Web/API/GlobalEventHandlers/onclick
diff --git a/files/en-us/_wikihistory.json b/files/en-us/_wikihistory.json
index bc7524783871e0b..7f3599582c3f0f1 100644
--- a/files/en-us/_wikihistory.json
+++ b/files/en-us/_wikihistory.json
@@ -1,4 +1,14 @@
{
+ "/Web/API/BaseAudioContext/statechange_event": {
+ "modified": "2020-10-23T15:49:13.972Z",
+ "contributors": [
+ "bryanbraun",
+ "1valdis",
+ "fscholz",
+ "Jedipedia",
+ "chrisdavidmills"
+ ]
+ },
"/Web/Guide/Houdini": {
"modified": "2020-07-16T03:51:08.991Z",
"contributors": [
@@ -10346,44 +10356,6 @@
"AllenChong"
]
},
- "Learn/JavaScript/Asynchronous/Async_await": {
- "modified": "2020-12-09T11:03:17.062Z",
- "contributors": [
- "chrisdavidmills",
- "prosovskyf",
- "hexagonrecursion",
- "SUM1",
- "ReedyBear",
- "tim_cannon",
- "Flimm",
- "kruschk",
- "enejko",
- "Sheppy",
- "tashpool",
- "wcarlson-va"
- ]
- },
- "Learn/JavaScript/Asynchronous/Choosing_the_right_approach": {
- "modified": "2020-10-15T22:17:14.520Z",
- "contributors": [
- "JohnnyMu-Cn",
- "vgiffin",
- "chrisdavidmills",
- "kruschk",
- "tywmick",
- "enejko",
- "Sheppy"
- ]
- },
- "Learn/JavaScript/Asynchronous/Concepts": {
- "modified": "2020-07-16T22:33:27.691Z",
- "contributors": [
- "CodeDotJS",
- "chrisdavidmills",
- "Sheppy",
- "Hallo89"
- ]
- },
"Learn/JavaScript/Asynchronous/Introducing": {
"modified": "2020-11-05T06:58:50.627Z",
"contributors": [
@@ -10418,22 +10390,6 @@
"Sheppy"
]
},
- "Learn/JavaScript/Asynchronous/Timeouts_and_intervals": {
- "modified": "2020-08-05T00:09:23.001Z",
- "contributors": [
- "Rafael_Green",
- "chrisdavidmills",
- "A.Faturechi",
- "nkalvi",
- "mariusmucenicu",
- "Zearin_Galaurum",
- "ZhenWang-Jen",
- "jeffro94",
- "tashpool",
- "Sheppy",
- "k-lusine"
- ]
- },
"Learn/JavaScript/Building_blocks": {
"modified": "2020-07-16T22:31:06.092Z",
"contributors": [
@@ -28054,27 +28010,6 @@
"Sheppy"
]
},
- "Web/API/AudioTrackList/onaddtrack": {
- "modified": "2020-10-15T22:07:20.667Z",
- "contributors": [
- "sideshowbarker",
- "Sheppy"
- ]
- },
- "Web/API/AudioTrackList/onchange": {
- "modified": "2020-10-15T22:07:21.232Z",
- "contributors": [
- "sideshowbarker",
- "Sheppy"
- ]
- },
- "Web/API/AudioTrackList/onremovetrack": {
- "modified": "2020-10-15T22:07:25.247Z",
- "contributors": [
- "sideshowbarker",
- "Sheppy"
- ]
- },
"Web/API/AudioTrackList/removetrack_event": {
"modified": "2020-10-15T22:16:55.584Z",
"contributors": [
@@ -28123,13 +28058,6 @@
"1valdis"
]
},
- "Web/API/AudioWorkletNode/onprocessorerror": {
- "modified": "2020-10-15T22:20:33.024Z",
- "contributors": [
- "chrisdavidmills",
- "1valdis"
- ]
- },
"Web/API/AudioWorkletNode/parameters": {
"modified": "2020-10-15T22:20:31.959Z",
"contributors": [
@@ -28147,6 +28075,13 @@
"chrisdavidmills"
]
},
+ "Web/API/AudioWorkletNode/processorerror_event": {
+ "modified": "2020-10-15T22:20:33.024Z",
+ "contributors": [
+ "chrisdavidmills",
+ "1valdis"
+ ]
+ },
"Web/API/AudioWorkletProcessor": {
"modified": "2020-10-15T22:20:46.279Z",
"contributors": [
@@ -28643,16 +28578,6 @@
"teoli"
]
},
- "Web/API/BaseAudioContext/onstatechange": {
- "modified": "2020-10-23T15:49:13.972Z",
- "contributors": [
- "bryanbraun",
- "1valdis",
- "fscholz",
- "Jedipedia",
- "chrisdavidmills"
- ]
- },
"Web/API/BaseAudioContext/sampleRate": {
"modified": "2020-10-15T21:28:08.709Z",
"contributors": [
@@ -38080,43 +38005,6 @@
"Sheppy"
]
},
- "Web/API/Document/onafterscriptexecute": {
- "modified": "2020-10-15T21:07:56.641Z",
- "contributors": [
- "mfuji09",
- "mfluehr",
- "wbamberg",
- "fscholz",
- "valtlai",
- "teoli",
- "MHasan",
- "kscarfone",
- "vishu_gawli",
- "Sheppy",
- "ethertank",
- "ziyunfei",
- "Midnightaz",
- "Johnjbarton"
- ]
- },
- "Web/API/Document/onbeforescriptexecute": {
- "modified": "2020-10-15T21:07:58.847Z",
- "contributors": [
- "wbamberg",
- "fscholz",
- "valtlai",
- "teoli",
- "jsx",
- "kscarfone",
- "vishu_gawli",
- "nairakhil13",
- "Sheppy",
- "ethertank",
- "ziyunfei",
- "Midnightaz",
- "Johnjbarton"
- ]
- },
"Web/API/Document/onoffline": {
"modified": "2019-03-23T23:14:56.082Z",
"contributors": [
@@ -38138,15 +38026,6 @@
"arivu86"
]
},
- "Web/API/Document/onvisibilitychange": {
- "modified": "2020-10-15T21:55:48.855Z",
- "contributors": [
- "sideshowbarker",
- "fscholz",
- "jpmedley",
- "chrisdavidmills"
- ]
- },
"Web/API/Document/open": {
"modified": "2020-10-15T21:11:18.087Z",
"contributors": [
@@ -44801,33 +44680,6 @@
"wbamberg"
]
},
- "Web/API/FileReader/onabort": {
- "modified": "2020-12-09T19:56:06.234Z",
- "contributors": [
- "bershanskiy",
- "NotWoods"
- ]
- },
- "Web/API/FileReader/onerror": {
- "modified": "2020-12-09T19:57:36.155Z",
- "contributors": [
- "bershanskiy",
- "1j01",
- "pungggi"
- ]
- },
- "Web/API/FileReader/onload": {
- "modified": "2020-10-15T21:41:07.311Z",
- "contributors": [
- "nujabes403",
- "nongomacoders",
- "fscholz",
- "prateekrbhutani",
- "teoli",
- "mrenty",
- "nihey"
- ]
- },
"Web/API/FileReader/progress_event": {
"modified": "2020-10-15T22:15:39.291Z",
"contributors": [
@@ -54578,20 +54430,6 @@
"louisremi"
]
},
- "Web/API/IDBDatabaseException": {
- "modified": "2020-10-15T21:10:02.682Z",
- "contributors": [
- "fscholz",
- "jpmedley",
- "kscarfone",
- "pdm",
- "teoli",
- "mnoorenberghe",
- "grendel",
- "kathyw",
- "jswisher"
- ]
- },
"Web/API/IDBFactory": {
"modified": "2020-10-15T21:08:44.592Z",
"contributors": [
@@ -58078,6 +57916,15 @@
"jpmedley"
]
},
+ "Web/API/MediaKeySession/keystatuseschange_event": {
+ "modified": "2020-10-15T21:51:06.374Z",
+ "contributors": [
+ "sideshowbarker",
+ "connorshea",
+ "david_ross",
+ "jpmedley"
+ ]
+ },
"Web/API/MediaKeySession/load": {
"modified": "2020-10-15T21:37:05.888Z",
"contributors": [
@@ -58089,16 +57936,7 @@
"jpmedley"
]
},
- "Web/API/MediaKeySession/onkeystatuseschange": {
- "modified": "2020-10-15T21:51:06.374Z",
- "contributors": [
- "sideshowbarker",
- "connorshea",
- "david_ross",
- "jpmedley"
- ]
- },
- "Web/API/MediaKeySession/onmessage": {
+ "Web/API/MediaKeySession/message_event": {
"modified": "2020-10-15T21:51:05.016Z",
"contributors": [
"sideshowbarker",
@@ -61317,38 +61155,6 @@
"Jeremie"
]
},
- "Web/API/Navigator/Online_and_offline_events": {
- "modified": "2020-09-15T12:54:20.249Z",
- "contributors": [
- "OtterOne",
- "chrisdavidmills",
- "torazaburo",
- "edwardcasbon",
- "artistics-weddings",
- "schmod",
- "maxbarrett",
- "kazaf",
- "PierreBergamin",
- "jsx",
- "Jeremie",
- "kscarfone",
- "teoli",
- "HaNdTriX",
- "lmorchard",
- "DavidWalsh",
- "jswisher",
- "john_smith",
- "ethertank",
- "grendel",
- "Sheppy",
- "sebmozilla",
- "Nickolay",
- "Mgjbot",
- "Leandro Mercês Xavier",
- "BenoitL",
- "Jresig"
- ]
- },
"Web/API/Navigator/activeVRDisplays": {
"modified": "2020-10-15T21:46:04.268Z",
"contributors": [
@@ -64431,15 +64237,6 @@
"jpmedley"
]
},
- "Web/API/OfflineAudioContext/oncomplete": {
- "modified": "2020-10-15T21:29:53.436Z",
- "contributors": [
- "sideshowbarker",
- "chrisdavidmills",
- "fscholz",
- "abbycar"
- ]
- },
"Web/API/OfflineAudioContext/resume": {
"modified": "2020-10-15T21:44:23.667Z",
"contributors": [
@@ -65949,16 +65746,6 @@
"kscarfone"
]
},
- "Web/API/Performance/onresourcetimingbufferfull": {
- "modified": "2020-10-15T21:41:14.201Z",
- "contributors": [
- "chrisdavidmills",
- "fscholz",
- "jpmedley",
- "rolfedh",
- "AFBarstow"
- ]
- },
"Web/API/Performance/resourcetimingbufferfull_event": {
"modified": "2020-10-15T21:41:10.224Z",
"contributors": [
@@ -67579,14 +67366,6 @@
"jpmedley"
]
},
- "Web/API/PresentationAvailability/onchange": {
- "modified": "2020-10-15T21:47:48.905Z",
- "contributors": [
- "lucian95",
- "david_ross",
- "MashKao"
- ]
- },
"Web/API/PresentationAvailability/value": {
"modified": "2020-10-15T21:47:48.921Z",
"contributors": [
@@ -86889,18 +86668,6 @@
"louisremi"
]
},
- "Web/API/Window/onappinstalled": {
- "modified": "2020-10-15T21:47:08.944Z",
- "contributors": [
- "Oaphi",
- "sideshowbarker",
- "wbamberg",
- "chrisdavidmills",
- "marcoscaceres",
- "fscholz",
- "teoli"
- ]
- },
"Web/API/Window/onbeforeinstallprompt": {
"modified": "2020-10-15T21:36:30.007Z",
"contributors": [
diff --git a/files/en-us/glossary/algorithm/index.md b/files/en-us/glossary/algorithm/index.md
index 4b646f66d6c7f66..68ddb770b7d8aa1 100644
--- a/files/en-us/glossary/algorithm/index.md
+++ b/files/en-us/glossary/algorithm/index.md
@@ -12,7 +12,7 @@ In other words, an algorithm is a means of describing a way to solve a problem s
For example:
- A cooking recipe is a simple algorithm for humans.
-- A sorting algorithm is often used in computer programming to explain a machine how to sort data.
+- A sorting algorithm is often used in computer programming to explain to a machine how to sort data.
Common algorithms are Pathfinding algorithms such as the Traveling Salesman Problem, Tree Traversal algorithms and so on.
diff --git a/files/en-us/glossary/ice/index.md b/files/en-us/glossary/ice/index.md
index c55618bc8ac47a0..df4904e22ade11f 100644
--- a/files/en-us/glossary/ice/index.md
+++ b/files/en-us/glossary/ice/index.md
@@ -21,5 +21,5 @@ The framework algorithm looks for the lowest-latency path for connecting the two
- [WebRTC](/en-US/docs/Web/API/WebRTC_API), the principal web-related protocol which uses ICE
- [WebRTC protocols](/en-US/docs/Web/API/WebRTC_API/Protocols)
-- {{rfc("5245")}}, the IETF specification for ICE
+- {{rfc("8445")}}, the IETF specification for ICE
- {{domxref("RTCIceCandidate")}}, the interface representing a ICE candidate
diff --git a/files/en-us/glossary/javascript/index.md b/files/en-us/glossary/javascript/index.md
index 143444f3fe850b3..c6e68519be69def 100644
--- a/files/en-us/glossary/javascript/index.md
+++ b/files/en-us/glossary/javascript/index.md
@@ -19,7 +19,7 @@ JavaScript is primarily used in the browser, enabling developers to manipulate w
Conceived as a server-side language by Brendan Eich (then employed by the Netscape Corporation), JavaScript soon came to Netscape Navigator 2.0 in September 1995. JavaScript enjoyed immediate success and {{glossary("Microsoft Internet Explorer", "Internet Explorer 3.0")}} introduced JavaScript support under the name JScript in August 1996.
-In November 1996, Netscape began working with ECMA International to make JavaScript an industry standard. Since then, the standardized JavaScript is called ECMAScript and specified under ECMA-262, whose latest (eleventh, ES2020) edition is available as of June 2020.
+In November 1996, Netscape began working with Ecma International to make JavaScript an industry standard. Since then, the standardized JavaScript is called ECMAScript and specified under ECMA-262, whose latest (twelfth, ES2021) edition is available as of June 2021.
Recently, JavaScript's popularity has expanded even further through the successful [Node.js](https://nodejs.org/) platform—the most popular cross-platform JavaScript runtime environment outside the browser. Node.js - built using [Chrome's V8 JavaScript Engine]() - allows developers to use JavaScript as a scripting language to automate things on a computer and build fully functional {{Glossary("HTTP")}} and {{Glossary("WebSockets")}} servers.
diff --git a/files/en-us/learn/accessibility/html/index.md b/files/en-us/learn/accessibility/html/index.md
index def3a7532d2de4d..9c0d07e52b9026c 100644
--- a/files/en-us/learn/accessibility/html/index.md
+++ b/files/en-us/learn/accessibility/html/index.md
@@ -351,17 +351,17 @@ Basically, the {{htmlattrxref("tabindex")}} attribute is primarily intended to a
- `tabindex="0"` — as indicated above, this value allows elements that are not normally tabbable to become tabbable. This is the most useful value of `tabindex`.
- `tabindex="-1"` — this allows not normally tabbable elements to receive focus programmatically, e.g., via JavaScript, or as the target of links.
-Whilst the above addition allows us to tab to the buttons, it does not allow us to activate them via the Enter/Return key. To do that, we had to add the following bit of JavaScript trickery:
+While the above addition allows us to tab to the buttons, it does not allow us to activate them via the Enter/Return key. To do that, we had to add the following bit of JavaScript trickery:
```js
document.onkeydown = function(e) {
- if(e.keyCode === 13) { // The Enter/Return key
+ if(e.key === "Enter") { // The Enter/Return key
document.activeElement.click();
}
};
```
-Here we add a listener to the `document` object to detect when a button has been pressed on the keyboard. We check what button was pressed via the event object's [`keyCode`](/en-US/docs/Web/API/KeyboardEvent/keyCode) property; if it is the keycode that matches Return/Enter, we run the function stored in the button's `onclick` handler using `document.activeElement.click()`. [`activeElement`](/en-US/docs/Web/API/Document/activeElement) which gives us the element that is currently focused on the page.
+Here we add a listener to the `document` object to detect when a button has been pressed on the keyboard. We check what button was pressed via the event object's [`key`](/en-US/docs/Web/API/KeyboardEvent/key) property; if the key pressed is Enter/Return, we run the function stored in the button's `onclick` handler using `document.activeElement.click()`. [`activeElement`](/en-US/docs/Web/API/Document/activeElement) which gives us the element that is currently focused on the page.
This is a lot of extra hassle to build the functionality back in. And there's bound to be other problems with it. **Better to just use the right element for the right job in the first place.**
@@ -535,7 +535,7 @@ Unfortunately, most screen readers don't seem to associate figure captions with
There may be times where an image is included in a page's design, but its primary purpose is for visual decoration. You'll notice in the code example above that the image's `alt` attribute is empty — this is to make screen readers recognize the image, but not attempt to describe the image (instead they'd just say "image", or similar).
-The reason to use an empty `alt` instead of not including it is because many screen readers announce the whole image URL if no `alt` is provided. In the above example, the image is acting as a visual decoration to the heading it's associated with. In cases like this, and in cases where an image is only decoration and has no content value, you should include an empty `alt` in your `img` elements. Another alternative is to use the aria [`role`](/en-US/docs/Web/accessibility/ARIA/roles) attribute [`role="presentation"`](/en-US/docs/Web/accessibility/ARIA/roles/presentation_role) as this also stops screen readers from reading out alternative text.
+The reason to use an empty `alt` instead of not including it is because many screen readers announce the whole image URL if no `alt` is provided. In the above example, the image is acting as a visual decoration to the heading it's associated with. In cases like this, and in cases where an image is only decoration and has no content value, you should include an empty `alt` in your `img` elements. Another alternative is to use the aria [`role`](/en-US/docs/Web/Accessibility/ARIA/Roles) attribute [`role="presentation"`](/en-US/docs/Web/Accessibility/ARIA/Roles/presentation_role) as this also stops screen readers from reading out alternative text.
> **Note:** If possible you should use CSS to display images that are only decorative.
diff --git a/files/en-us/learn/common_questions/what_is_a_web_server/index.md b/files/en-us/learn/common_questions/what_is_a_web_server/index.md
index e7b9f50b1afc247..ad47e846f4f7948 100644
--- a/files/en-us/learn/common_questions/what_is_a_web_server/index.md
+++ b/files/en-us/learn/common_questions/what_is_a_web_server/index.md
@@ -38,7 +38,7 @@ In this article, we explain what web servers are, how web servers work, and why
The term _web server_ can refer to hardware or software, or both of them working together.
-1. On the hardware side, a web server is a computer that stores web server software and a website's component files. (for example, HTML documents, images, CSS stylesheets, and JavaScript files) A web server connects to the Internet and supports physical data interchange with other devices connected to the web.
+1. On the hardware side, a web server is a computer that stores web server software and a website's component files (for example, HTML documents, images, CSS stylesheets, and JavaScript files). A web server connects to the Internet and supports physical data interchange with other devices connected to the web.
2. On the software side, a web server includes several parts that control how web users access hosted files. At a minimum, this is an _HTTP server_. An HTTP server is software that understands {{Glossary("URL","URLs")}} (web addresses) and {{Glossary("HTTP")}} (the protocol your browser uses to view webpages). An HTTP server can be accessed through the domain names of the websites it stores, and it delivers the content of these hosted websites to the end user's device.
At the most basic level, whenever a browser needs a file that is hosted on a web server, the browser requests the file via HTTP. When the request reaches the correct (hardware) web server, the (software) _HTTP server_ accepts the request, finds the requested document, and sends it back to the browser, also through HTTP. (If the server doesn't find the requested document, it returns a [404](/en-US/docs/Web/HTTP/Status/404) response instead.)
diff --git a/files/en-us/learn/css/building_blocks/cascade_tasks/index.md b/files/en-us/learn/css/building_blocks/cascade_tasks/index.md
index 37291367954b8bc..5a4b184d62e29fc 100644
--- a/files/en-us/learn/css/building_blocks/cascade_tasks/index.md
+++ b/files/en-us/learn/css/building_blocks/cascade_tasks/index.md
@@ -7,7 +7,7 @@ tags:
---
{{LearnSidebar}}
-The aim of this task is to help you check your understanding of some of the values and units that we looked at in the lesson on [The Cascade and Inheritance](/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance).
+The aim of this task is to help you check your understanding of the universal property values for controlling inheritance that we looked at in the lesson on [The Cascade and Inheritance](/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance).
> **Note:** You can try out solutions in the interactive editors below, however, it may be helpful to download the code and use an online tool such as [CodePen](https://codepen.io/), [jsFiddle](https://jsfiddle.net/), or [Glitch](https://glitch.com/) to work on the tasks.
>
diff --git a/files/en-us/learn/css/css_layout/floats/index.md b/files/en-us/learn/css/css_layout/floats/index.md
index 58650b22e497236..be7c4311da0d00c 100644
--- a/files/en-us/learn/css/css_layout/floats/index.md
+++ b/files/en-us/learn/css/css_layout/floats/index.md
@@ -51,7 +51,7 @@ In this article we'll just concentrate on the proper uses of floats.
## A simple float example
-Let's explore the use of floats. We'll start with a really simple example involving floating a block of text around an element. You can follow along by creating a new `index.html` file on your computer, filling it with a [simple HTML template](https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html), and inserting the below code into it at the appropriate places. At the bottom of the section, you can see a live example of what the final code should look like.
+Let's explore the use of floats. We'll start with a really simple example involving floating a block of text around an element. You can follow along by creating a new `index.html` file on your computer, filling it with a [simple HTML template](https://github.com/mdn/learning-area/blob/main/html/introduction-to-html/getting-started/index.html), and inserting the below code into it at the appropriate places. At the bottom of the section, you can see a live example of what the final code should look like.
First, we'll start off with some simple HTML. Add the following to your HTML body, removing anything that was inside there before:
@@ -118,7 +118,7 @@ To float the box, add the {{cssxref("float")}} and {{cssxref("margin-right")}} p
Now if you save and refresh you'll see something like the following:
-{{ EmbedLiveSample('Floating_the_box', '100%', 500) }}
+{{EmbedLiveSample('Floating_the_box', '100%', 500)}}
Let's think about how the float works. The element with the float set on it (the {{htmlelement("div")}} element in this case) is taken out of the normal layout flow of the document and stuck to the left-hand side of its parent container ({{htmlelement("body")}}, in this case). Any content that would come below the floated element in the normal layout flow will now wrap around it instead, filling up the space to the right-hand side of it as far up as the top of the floated element. There, it will stop.
@@ -177,7 +177,7 @@ body {
}
```
-{{ EmbedLiveSample('Visualizing_the_float', '100%', 500) }}
+{{EmbedLiveSample('Visualizing_the_float', '100%', 500)}}
The [line boxes](/en-US/docs/Web/CSS/Visual_formatting_model#line_boxes) of our following element have been shortened so the text runs around the float, but due to the float being removed from normal flow the box around the paragraph still remains full width.
@@ -203,7 +203,6 @@ In your HTML from the previous example, add a class of `cleared` to the second p
Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
-
```
```css hidden
@@ -235,7 +234,7 @@ body {
}
```
-{{ EmbedLiveSample('Clearing_floats', '100%', 600) }}
+{{EmbedLiveSample('Clearing_floats', '100%', 600)}}
You should see that the second paragraph now clears the floated element and no longer comes up alongside it. The `clear` property accepts the following values:
@@ -273,14 +272,14 @@ In addition, remove the original `.cleared` class:
```css
.cleared {
- clear: left;
+ clear: left;
}
```
You'll see that, just like in the example where we put a background color on the paragraph, the background color runs behind the float.
```html hidden
-
Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
+
Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
```
@@ -310,7 +309,7 @@ body {
}
```
-{{ EmbedLiveSample('The_problem', '100%', 600) }}
+{{EmbedLiveSample('The_problem', '100%', 600)}}
Once again, this is because the float has been taken out of normal flow. Clearing the following element won't work as it did before. This is a problem if you want the box to wrap jointly around the floated item as well as the text of the first paragraph that wraps around the float, while also having the following content cleared of the box. There are three potential ways to deal with this, two of which work in all browsers — yet are slightly hacky — and a third, newer way that deals with this situation properly.
@@ -373,7 +372,7 @@ body {
}
```
-{{ EmbedLiveSample('The_clearfix_hack', '100%', 600) }}
+{{EmbedLiveSample('The_clearfix_hack', '100%', 600)}}
### Using overflow
@@ -428,7 +427,7 @@ body {
}
```
-{{ EmbedLiveSample('Using_overflow', '100%', 600) }}
+{{EmbedLiveSample('Using_overflow', '100%', 600)}}
This example works by creating what's known as a **block formatting context** (BFC). This is like a mini layout inside your page, inside of which everything is contained. This means our floated element is contained inside the BFC, and the background runs behind both items. This will usually work; however, in certain cases you might find unwanted scrollbars or clipped shadows due to unintended consequences of using overflow.
@@ -483,7 +482,7 @@ body {
}
```
-{{ EmbedLiveSample('display_flow-root', '100%', 600) }}
+{{EmbedLiveSample('display_flow-root', '100%', 600)}}
## Test your skills!
diff --git a/files/en-us/learn/css/css_layout/fundamental_layout_comprehension/index.md b/files/en-us/learn/css/css_layout/fundamental_layout_comprehension/index.md
index 6e7e5ae29f40864..0c7f5b4050f214f 100644
--- a/files/en-us/learn/css/css_layout/fundamental_layout_comprehension/index.md
+++ b/files/en-us/learn/css/css_layout/fundamental_layout_comprehension/index.md
@@ -1,5 +1,5 @@
---
-title: 'Fundamental layout comprehension'
+title: "Fundamental layout comprehension"
slug: Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension
tags:
- Assessment
@@ -8,6 +8,7 @@ tags:
- Layout
- Learn
---
+
{{LearnSidebar}}
{{PreviousMenu("Learn/CSS/CSS_layout/Supporting_Older_Browsers", "Learn/CSS/CSS_layout")}}
@@ -63,10 +64,10 @@ If you would like your work assessed, or are stuck and want to ask for help:
1. Put your work into an online shareable editor such as [CodePen](https://codepen.io/), [jsFiddle](https://jsfiddle.net/), or [Glitch](https://glitch.com/). You can write the code yourself, or use the starting point files linked to in the above sections.
2. Write a post asking for assessment and/or help at the [MDN Discourse forum Learning category](https://discourse.mozilla.org/c/mdn/learn). Your post should include:
- - A descriptive title such as "Assessment wanted for Fundamental Layout Comprehension".
- - Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.
- - A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.
- - A link to the actual task or assessment page, so we can find the question you want help with.
+ - A descriptive title such as "Assessment wanted for Fundamental Layout Comprehension".
+ - Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.
+ - A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.
+ - A link to the actual task or assessment page, so we can find the question you want help with.
{{PreviousMenu("Learn/CSS/CSS_layout/Supporting_Older_Browsers", "Learn/CSS/CSS_layout")}}
@@ -83,4 +84,4 @@ If you would like your work assessed, or are stuck and want to ask for help:
- [Beginner's guide to media queries](/en-US/docs/Learn/CSS/CSS_layout/Media_queries)
- [Legacy layout methods](/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods)
- [Supporting older browsers](/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers)
-- [Fundamental layout comprehension assessment](/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension)
+- Fundamental layout comprehension assessment
diff --git a/files/en-us/learn/css/css_layout/introduction/index.md b/files/en-us/learn/css/css_layout/introduction/index.md
index 680a90fcc81da36..14cf049666b60b3 100644
--- a/files/en-us/learn/css/css_layout/introduction/index.md
+++ b/files/en-us/learn/css/css_layout/introduction/index.md
@@ -197,7 +197,7 @@ Similar to flexbox, we enable Grid Layout with its specific display value — `d
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
- grid-gap: 10px;
+ gap: 10px;
}
```
@@ -235,7 +235,7 @@ Once you have a grid, you can explicitly place your items on it, rather than rel
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
- grid-gap: 10px;
+ gap: 10px;
}
.box1 {
diff --git a/files/en-us/learn/css/styling_text/styling_links/index.md b/files/en-us/learn/css/styling_text/styling_links/index.md
index 5fc642b7f187829..3901e34535a16fc 100644
--- a/files/en-us/learn/css/styling_text/styling_links/index.md
+++ b/files/en-us/learn/css/styling_text/styling_links/index.md
@@ -315,8 +315,8 @@ Let's look at some HTML and CSS that will give us the effect we want. First, som
```html
```
Next, the CSS:
@@ -354,7 +354,7 @@ a:active {
color: red;
}
-a[href*="#"] {
+a[href^="http"] {
background: url('external-link-52.png') no-repeat 100% 0;
background-size: 16px 16px;
padding-right: 19px;
@@ -369,7 +369,7 @@ We also use {{cssxref("background-size")}} to specify the size we want the backg
Finally, we set some {{cssxref("padding-right")}} on the links to make space for the background image to appear in, so we aren't overlapping it with the text.
-A final word: how did we select just external links? Well, if you are writing your [HTML links](/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks) properly, you should only be using absolute URLs for external links — it is more efficient to use relative links to link to other parts of your own site (as with the first link). The text "http" should therefore only appear in external links (like the second and third ones), and we can select this with an [attribute selector](/en-US/docs/Learn/CSS/Building_blocks/Selectors#attribute_selectors): `a[href*="http"]` selects {{htmlelement("a")}} elements, but only if they have an {{htmlattrxref("href","a")}} attribute with a value that contains "http" somewhere inside it.
+A final word: how did we select just external links? Well, if you are writing your [HTML links](/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks) properly, you should only be using absolute URLs for external links — it is more efficient to use relative links to link to other parts of your own site (as with the first link). The text "http" should therefore only appear in external links (like the second and third ones), and we can select this with an [attribute selector](/en-US/docs/Learn/CSS/Building_blocks/Selectors#attribute_selectors): `a[href^="http"]` selects {{htmlelement("a")}} elements, but only if they have an {{htmlattrxref("href","a")}} attribute with a value that begins with "http".
So that's it. Try revisiting the active learning section above and trying this new technique out!
diff --git a/files/en-us/learn/forms/form_validation/index.md b/files/en-us/learn/forms/form_validation/index.md
index 1a7ffcac8a12f0d..f8e4c17bfcf0ace 100644
--- a/files/en-us/learn/forms/form_validation/index.md
+++ b/files/en-us/learn/forms/form_validation/index.md
@@ -574,7 +574,7 @@ input:focus:invalid {
}
```
-Now lets look at the JavaScript that implements the custom error validation.
+Now let's look at the JavaScript that implements the custom error validation.
```js
// There are many ways to pick a DOM node; here we get the form itself and the email
diff --git a/files/en-us/learn/html/introduction_to_html/the_head_metadata_in_html/index.md b/files/en-us/learn/html/introduction_to_html/the_head_metadata_in_html/index.md
index 3c747d6584e0eba..c15508da4636711 100644
--- a/files/en-us/learn/html/introduction_to_html/the_head_metadata_in_html/index.md
+++ b/files/en-us/learn/html/introduction_to_html/the_head_metadata_in_html/index.md
@@ -236,7 +236,7 @@ Just about all websites you'll use in the modern day will employ {{glossary("CSS
```
-- The {{htmlelement("script")}} element should also go into the head, and should include a `src` attribute containing the path to the JavaScript you want to load, and `defer`, which basically instructs the browser to load the JavaScript after the page has finished parsing the HTML. This is useful as it makes sure that the HTML is all loaded before the JavaScript runs, so that you don't get errors resulting from JavaScript trying to access an HTML element that doesn't exist on the page yet. There are actually a number of ways to handle loading JavaScript on your page, but this is the most foolproof one to use for modern browsers (for others, read [Script loading strategies](/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#script_loading_strategies)).
+- The {{htmlelement("script")}} element should also go into the head, and should include a `src` attribute containing the path to the JavaScript you want to load, and `defer`, which basically instructs the browser to load the JavaScript after the page has finished parsing the HTML. This is useful as it makes sure that the HTML is all loaded before the JavaScript runs, so that you don't get errors resulting from JavaScript trying to access an HTML element that doesn't exist on the page yet. There are actually a number of ways to handle loading JavaScript on your page, but this is the most reliable one to use for modern browsers (for others, read [Script loading strategies](/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#script_loading_strategies)).
```html
diff --git a/files/en-us/learn/javascript/asynchronous/async_await/index.md b/files/en-us/learn/javascript/asynchronous/async_await/index.md
deleted file mode 100644
index 4dc77dc471cbce8..000000000000000
--- a/files/en-us/learn/javascript/asynchronous/async_await/index.md
+++ /dev/null
@@ -1,591 +0,0 @@
----
-title: Making asynchronous programming easier with async and await
-slug: Learn/JavaScript/Asynchronous/Async_await
-tags:
- - Beginner
- - CodingScripting
- - Guide
- - JavaScript
- - Learn
- - Promises
- - async
- - asynchronous
- - await
----
-{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}
-
-More recent additions to the JavaScript language are [async functions](/en-US/docs/Web/JavaScript/Reference/Statements/async_function) and the [`await`](/en-US/docs/Web/JavaScript/Reference/Operators/await) keyword, added in ECMAScript 2017. These features basically act as syntactic sugar on top of promises, making asynchronous code easier to write and to read afterwards. They make async code look more like old-school synchronous code, so they're well worth learning. This article gives you what you need to know.
-
-
-
-
-
Prerequisites:
-
- Basic computer literacy, a reasonable understanding of JavaScript
- fundamentals, an understanding of async code in general and promises.
-
-
-
-
Objective:
-
To understand the use of async/await.
-
-
-
-
-## The basics of async/await
-
-There are two parts to using async/await in your code.
-
-### The async keyword
-
-First of all we have the `async` keyword, which you put in front of a function declaration to turn it into an [async function](/en-US/docs/Web/JavaScript/Reference/Statements/async_function). An async function is a function that knows how to expect the possibility of the `await` keyword being used to invoke asynchronous code.
-
-Try typing the following lines into your browser's JS console:
-
-```js
-function hello() { return "Hello" };
-hello();
-```
-
-The function returns "Hello" — nothing special, right?
-
-But what if we turn this into an async function? Try the following:
-
-```js
-async function hello() { return "Hello" };
-hello();
-```
-
-Ah. Invoking the function now returns a promise. This is one of the traits of async functions — their return values are guaranteed to be converted to promises.
-
-You can also create an [async function expression](/en-US/docs/Web/JavaScript/Reference/Operators/async_function), like so:
-
-```js
-let hello = async function() { return "Hello" };
-hello();
-```
-
-And you can use [arrow functions](/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions):
-
-```js
-let hello = async () => "Hello";
-```
-
-These all do basically the same thing.
-
-To actually consume the value returned when the promise fulfills, since it is returning a promise, we could use a `.then()` block:
-
-```js
-hello().then((value) => console.log(value))
-```
-
-or even just shorthand such as
-
-```js
-hello().then(console.log)
-```
-
-Like we saw in the last article.
-
-So the `async` keyword is added to functions to tell them to return a promise rather than directly returning the value.
-
-### The await keyword
-
-The advantage of an async function only becomes apparent when you combine it with the [await](/en-US/docs/Web/JavaScript/Reference/Operators/await) keyword. `await` only works inside async functions within regular JavaScript code, however it can be used on its own with [JavaScript modules.](/en-US/docs/Web/JavaScript/Guide/Modules)
-
-`await` can be put in front of any async promise-based function to pause your code on that line until the promise fulfills, then return the resulting value.
-
-You can use `await` when calling any function that returns a Promise, including web API functions.
-
-Here is a trivial example:
-
-```js
-async function hello() {
- return await Promise.resolve("Hello");
-};
-
-hello().then(alert);
-```
-
-Of course, the above example is not very useful, although it does serve to illustrate the syntax. Let's move on and look at a real example.
-
-## Rewriting promise code with async/await
-
-Let's look back at a simple fetch example that we saw in the previous article:
-
-```js
-fetch('coffee.jpg')
- .then(response => {
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- return response.blob();
- })
- .then(myBlob => {
- let objectURL = URL.createObjectURL(myBlob);
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
- })
- .catch(e => {
- console.log('There has been a problem with your fetch operation: ' + e.message);
- });
-```
-
-By now, you should have a reasonable understanding of promises and how they work, but let's convert this to use async/await to see how much simpler it makes things:
-
-```js
-async function myFetch() {
- let response = await fetch('coffee.jpg');
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
-
- let myBlob = await response.blob();
-
- let objectURL = URL.createObjectURL(myBlob);
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
-}
-
-myFetch()
- .catch(e => {
- console.log('There has been a problem with your fetch operation: ' + e.message);
- });
-```
-
-It makes code much simpler and easier to understand — no more `.then()` blocks everywhere!
-
-Since an `async` keyword turns a function into a promise, you could refactor your code to use a hybrid approach of promises and await, bringing the second half of the function out into a new block to make it more flexible:
-
-```js
-async function myFetch() {
- let response = await fetch('coffee.jpg');
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- return await response.blob();
-}
-
-myFetch()
- .then(blob => {
- let objectURL = URL.createObjectURL(blob);
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
- })
- .catch(e => console.log(e));
-```
-
-You can try typing in the example yourself, or running our [live example](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await.html) (see also the [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await.html)).
-
-### But how does it work?
-
-You'll note that we've wrapped the code inside a function, and we've included the `async` keyword before the `function` keyword. This is necessary — you have to create an async function to define a block of code in which you'll run your async code; as we said earlier, `await` only works inside of async functions.
-
-Inside the `myFetch()` function definition you can see that the code closely resembles the previous promise version, but there are some differences. Instead of needing to chain a `.then()` block on to the end of each promise-based method, you just need to add an `await` keyword before the method call, and then assign the result to a variable. The `await` keyword causes the JavaScript runtime to pause your code on this line, not allowing further code to execute in the meantime until the async function call has returned its result — very useful if subsequent code relies on that result!
-
-Once that's complete, your code continues to execute starting on the next line. For example:
-
-```js
-let response = await fetch('coffee.jpg');
-```
-
-The response returned by the fulfilled `fetch()` promise is assigned to the `response` variable when that response becomes available, and the parser pauses on this line until that occurs. Once the response is available, the parser moves to the next line, which creates a [`Blob`](/en-US/docs/Web/API/Blob) out of it. This line also invokes an async promise-based method, so we use `await` here as well. When the result of operation returns, we return it out of the `myFetch()` function.
-
-This means that when we call the `myFetch()` function, it returns a promise, so we can chain a `.then()` onto the end of it inside which we handle displaying the blob onscreen.
-
-You are probably already thinking "this is really cool!", and you are right — fewer `.then()` blocks to wrap around code, and it mostly just looks like synchronous code, so it is really intuitive.
-
-### Adding error handling
-
-And if you want to add error handling, you've got a couple of options.
-
-You can use a synchronous [`try...catch`](/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) structure with `async`/`await`. This example expands on the first version of the code we showed above:
-
-```js
-async function myFetch() {
- try {
- let response = await fetch('coffee.jpg');
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- let myBlob = await response.blob();
- let objectURL = URL.createObjectURL(myBlob);
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
- } catch(e) {
- console.log(e);
- }
-}
-
-myFetch();
-```
-
-The `catch() {}` block is passed an error object, which we've called `e`; we can now log that to the console, and it will give us a detailed error message showing where in the code the error was thrown.
-
-If you wanted to use the second (refactored) version of the code that we showed above, you would be better off just continuing the hybrid approach and chaining a `.catch()` block onto the end of the `.then()` call, like this:
-
-```js
-async function myFetch() {
- let response = await fetch('coffee.jpg');
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- return await response.blob();
-}
-
-myFetch()
- .then(blob => {
- let objectURL = URL.createObjectURL(blob);
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
- })
- .catch(e => console.log(e));
-```
-
-This is because the `.catch()` block will catch errors occurring in both the async function call and the promise chain. If you used the `try`/`catch` block here, you might still get unhandled errors in the `myFetch()` function when it's called.
-
-You can find both of these examples on GitHub:
-
-- [simple-fetch-async-await-try-catch.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html) (see [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html))
-- [simple-fetch-async-await-promise-catch.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html) (see [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html))
-
-## Awaiting a Promise.all()
-
-async/await is built on top of [promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), so it's compatible with all the features offered by promises. This includes [`Promise.all()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) — you can quite happily await a `Promise.all()` call to get all the results returned into a variable in a way that looks like simple synchronous code. Again, let's return to [an example we saw in our previous article](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html). Keep it open in a separate tab so you can compare and contrast with the new version shown below.
-
-Converting this to async/await (see [live demo](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-all-async-await.html) and [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-all-async-await.html)), this now looks like so:
-
-```js
-async function fetchAndDecode(url, type) {
- let response = await fetch(url);
-
- let content;
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- } else {
- if(type === 'blob') {
- content = await response.blob();
- } else if(type === 'text') {
- content = await response.text();
- }
- }
- return content;
-}
-
-async function displayContent() {
- let coffee = fetchAndDecode('coffee.jpg', 'blob');
- let tea = fetchAndDecode('tea.jpg', 'blob');
- let description = fetchAndDecode('description.txt', 'text');
-
- let values = await Promise.all([coffee, tea, description]);
-
- let objectURL1 = URL.createObjectURL(values[0]);
- let objectURL2 = URL.createObjectURL(values[1]);
- let descText = values[2];
-
- let image1 = document.createElement('img');
- let image2 = document.createElement('img');
- image1.src = objectURL1;
- image2.src = objectURL2;
- document.body.appendChild(image1);
- document.body.appendChild(image2);
-
- let para = document.createElement('p');
- para.textContent = descText;
- document.body.appendChild(para);
-}
-
-displayContent()
- .catch(e => console.log(e));
-```
-
-You'll see that the `fetchAndDecode()` function has been converted easily into an async function with just a few changes. See the `Promise.all()` line:
-
-```js
-let values = await Promise.all([coffee, tea, description]);
-```
-
-By using `await` here we are able to get all the results of the three promises returned into the `values` array, when they are all available, in a way that looks very much like sync code. We've had to wrap all the code in a new async function, `displayContent()`, and we've not reduced the code by a lot of lines, but being able to move the bulk of the code out of the `.then()` block provides a nice, useful simplification, leaving us with a much more readable program.
-
-For error handling, we've included a `.catch()` block on our `displayContent()` call; this will handle errors occurring in both functions.
-
-> **Note:** It is also possible to use a sync [`finally`](/en-US/docs/Web/JavaScript/Reference/Statements/try...catch#the_finally_clause) block within an async function, in place of a [`.finally()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally) async block, to show a final report on how the operation went — you can see this in action in our [live example](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-finally-async-await.html) (see also the [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-finally-async-await.html)).
-
-## Handling async/await slowdown
-
-Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. The `await` keyword blocks execution of all the code that follows it until the promise fulfills, exactly as it would with a synchronous operation. It does allow other tasks to continue to run in the meantime, but the awaited code is blocked. For example:
-
-```js
-async function makeResult(items) {
- let newArr = [];
- for(let i = 0; i < items.length; i++) {
- newArr.push('word_' + i);
- }
- return newArr;
-}
-
-async function getResult() {
- let result = await makeResult(items); // Blocked on this line
- useThatResult(result); // Will not be executed before makeResult() is done
-}
-```
-
-As a result, your code could be slowed down by a significant number of awaited promises happening straight after one another. Each `await` will wait for the previous one to finish, whereas actually what you might want is for the promises to begin processing simultaneously, like they would do if we weren't using async/await.
-
-Let's look at two examples — [slow-async-await.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/slow-async-await.html) (see [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/slow-async-await.html)) and [fast-async-await.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/fast-async-await.html) (see [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/fast-async-await.html)). Both of them start off with a custom promise function that fakes an async process with a [`setTimeout()`](/en-US/docs/Web/API/setTimeout) call:
-
-```js
-function timeoutPromise(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- resolve("done");
- }, interval);
- });
-};
-```
-
-Then each one includes a `timeTest()` async function that awaits three `timeoutPromise()` calls:
-
-```js
-async function timeTest() {
- ...
-}
-```
-
-Each one ends by recording a start time, seeing how long the `timeTest()` promise takes to fulfill, then recording an end time and reporting how long the operation took in total:
-
-```js
-let startTime = Date.now();
-timeTest()
- .then(() => {
- let finishTime = Date.now();
- let timeTaken = finishTime - startTime;
- alert("Time taken in milliseconds: " + timeTaken);
- })
-```
-
-It is the `timeTest()` function that differs in each case.
-
-In the `slow-async-await.html` example, `timeTest()` looks like this:
-
-```js
-async function timeTest() {
- await timeoutPromise(3000);
- await timeoutPromise(3000);
- await timeoutPromise(3000);
-}
-```
-
-Here we await all three `timeoutPromise()` calls directly, making each one alert after 3 seconds. Each subsequent one is forced to wait until the last one finished — if you run the first example, you'll see the alert box reporting a total run time of around 9 seconds.
-
-In the `fast-async-await.html` example, `timeTest()` looks like this:
-
-```js
-async function timeTest() {
- const timeoutPromise1 = timeoutPromise(3000);
- const timeoutPromise2 = timeoutPromise(3000);
- const timeoutPromise3 = timeoutPromise(3000);
-
- await timeoutPromise1;
- await timeoutPromise2;
- await timeoutPromise3;
-}
-```
-
-Here we store the three `Promise` objects in variables, which has the effect of setting off their associated processes all running simultaneously.
-
-Next, we await their results — because the promises all started processing at essentially the same time, the promises will all fulfill at the same time; when you run the second example, you'll see the alert box reporting a total run time of just over 3 seconds!
-
-### Handling errors
-
-There is an issue with the above pattern however — it could lead to unhandled errors.
-
-Let's update the previous examples, this time adding a rejected promise and a `catch` statement in the end:
-
-```js
-function timeoutPromiseResolve(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- resolve("successful");
- }, interval);
- });
-};
-
-function timeoutPromiseReject(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- reject("error");
- }, interval);
- });
-};
-
-async function timeTest() {
- await timeoutPromiseResolve(5000);
- await timeoutPromiseReject(2000);
- await timeoutPromiseResolve(3000);
-}
-
-let startTime = Date.now();
-
-timeTest()
- .then(() => {})
- .catch(e => {
- console.log(e);
- let finishTime = Date.now();
- let timeTaken = finishTime - startTime;
- alert("Time taken in milliseconds: " + timeTaken);
- })
-```
-
-In the above example, the error is handled properly, and the alert appears after approximately 7 seconds.
-
-Now onto the second pattern:
-
-```js
-function timeoutPromiseResolve(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- resolve("successful");
- }, interval);
- });
-};
-
-function timeoutPromiseReject(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- reject("error");
- }, interval);
- });
-};
-
-async function timeTest() {
- const timeoutPromiseResolve1 = timeoutPromiseResolve(5000);
- const timeoutPromiseReject2 = timeoutPromiseReject(2000);
- const timeoutPromiseResolve3 = timeoutPromiseResolve(3000);
-
- await timeoutPromiseResolve1;
- await timeoutPromiseReject2;
- await timeoutPromiseResolve3;
-}
-
-let startTime = Date.now();
-
-timeTest()
- .then(() => {})
- .catch(e => {
- console.log(e);
- let finishTime = Date.now();
- let timeTaken = finishTime - startTime;
- alert("Time taken in milliseconds: " + timeTaken);
- })
-```
-
-In this example, we have an unhandled error in the console (after 2 seconds), and the alert appears after approximately 5 seconds.
-
-To start the promises in parallel and catch the error properly, we could use `Promise.all()`, as discussed earlier:
-
-```js
-function timeoutPromiseResolve(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- resolve("successful");
- }, interval);
- });
-};
-
-function timeoutPromiseReject(interval) {
- return new Promise((resolve, reject) => {
- setTimeout(function(){
- reject("error");
- }, interval);
- });
-};
-
-async function timeTest() {
- const timeoutPromiseResolve1 = timeoutPromiseResolve(5000);
- const timeoutPromiseReject2 = timeoutPromiseReject(2000);
- const timeoutPromiseResolve3 = timeoutPromiseResolve(3000);
-
- const results = await Promise.all([timeoutPromiseResolve1, timeoutPromiseReject2, timeoutPromiseResolve3]);
- return results;
-}
-
-let startTime = Date.now();
-
-timeTest()
- .then(() => {})
- .catch(e => {
- console.log(e);
- let finishTime = Date.now();
- let timeTaken = finishTime - startTime;
- alert("Time taken in milliseconds: " + timeTaken);
- })
-```
-
-In this example, the error is handled properly after around 2 seconds and we also see the alert after around 2 seconds.
-
-The `Promise.all()` rejects when any of the input promises are rejected. If you want all the promises to settle and then use some of their fulfilled values, even when some of
-them are rejected, you could use [`Promise.allSettled()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled) instead.
-
-## Async/await class methods
-
-As a final note before we move on, you can even add `async` in front of class/object methods to make them return promises, and `await` promises inside them. Take a look at the [ES class code we saw in our object-oriented JavaScript article](/en-US/docs/Learn/JavaScript/Objects/Inheritance#ecmascript_2015_classes), and then look at our modified version with an `async` method:
-
-```js
-class Person {
- constructor(first, last, age, gender, interests) {
- this.name = {
- first,
- last
- };
- this.age = age;
- this.gender = gender;
- this.interests = interests;
- }
-
- async greeting() {
- return await Promise.resolve(`Hi! I'm ${this.name.first}`);
- };
-
- farewell() {
- console.log(`${this.name.first} has left the building. Bye for now!`);
- };
-}
-
-let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);
-```
-
-The first class method could now be used something like this:
-
-```js
-han.greeting().then(console.log);
-```
-
-## Browser support
-
-One consideration when deciding whether to use async/await is support for older browsers. They are available in modern versions of most browsers, the same as promises; the main support problems come with Internet Explorer and Opera Mini.
-
-If you want to use async/await but are concerned about older browser support, you could consider using the [BabelJS](https://babeljs.io/) library — this allows you to write your applications using the latest JavaScript and let Babel figure out what changes if any are needed for your user's browsers. On encountering a browser that does not support async/await, Babel's polyfill can automatically provide fallbacks that work in older browsers.
-
-## Conclusion
-
-And there you have it — async/await provide a nice, simplified way to write async code that is simpler to read and maintain. Even with browser support being more limited than other async code mechanisms at the time of writing, it is well worth learning and considering for use, both for now and in the future.
-
-{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}
-
-## In this module
-
-- [General asynchronous programming concepts](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts)
-- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals)
-- [Graceful asynchronous programming with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
-- [Making asynchronous programming easier with async and await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)
-- [Choosing the right approach](/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach)
diff --git a/files/en-us/learn/javascript/asynchronous/choosing_the_right_approach/index.md b/files/en-us/learn/javascript/asynchronous/choosing_the_right_approach/index.md
deleted file mode 100644
index 08efa3ad56e346a..000000000000000
--- a/files/en-us/learn/javascript/asynchronous/choosing_the_right_approach/index.md
+++ /dev/null
@@ -1,460 +0,0 @@
----
-title: Choosing the right approach
-slug: Learn/JavaScript/Asynchronous/Choosing_the_right_approach
-tags:
- - Beginner
- - Intervals
- - JavaScript
- - Learn
- - Optimize
- - Promises
- - async
- - asynchronous
- - await
- - requestAnimationFrame
- - setInterval
- - setTimeout
- - timeouts
----
-{{LearnSidebar}}{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}
-
-To finish this module off, we'll provide a brief discussion of the different coding techniques and features we've discussed throughout, looking at which one you should use when, with recommendations and reminders of common pitfalls where appropriate. We'll probably add to this resource as time goes on.
-
-
-
-
-
Prerequisites:
-
- Basic computer literacy, a reasonable understanding of JavaScript
- fundamentals.
-
-
-
-
Objective:
-
- To be able to make a sound choice of when to use different asynchronous
- programming techniques.
-
-
-
-
-
-## Asynchronous callbacks
-
-Generally found in old-style APIs, involves a function being passed into another function as a parameter, which is then invoked when an asynchronous operation has been completed, so that the callback can in turn do something with the result. This is the precursor to promises; it's not as efficient or flexible. Use only when necessary.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------------- | ------------------------------ | -------------------------------- |
-| No | Yes (recursive callbacks) | Yes (nested callbacks) | No |
-
-### Code example
-
-An example that loads a resource via the [`XMLHttpRequest` API](/en-US/docs/Web/API/XMLHttpRequest) ([run it live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html), and [see the source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html)):
-
-```js
-function loadAsset(url, type, callback) {
- let xhr = new XMLHttpRequest();
- xhr.open('GET', url);
- xhr.responseType = type;
-
- xhr.onload = function() {
- callback(xhr.response);
- };
-
- xhr.send();
-}
-
-function displayImage(blob) {
- let objectURL = URL.createObjectURL(blob);
-
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
-}
-
-loadAsset('coffee.jpg', 'blob', displayImage);
-```
-
-### Pitfalls
-
-- Nested callbacks can be cumbersome and hard to read (i.e. "callback hell").
-- Failure callbacks need to be called once for each level of nesting, whereas with promises you can just use a single `.catch()` block to handle the errors for the entire chain.
-- Async callbacks just aren't very graceful.
-- Promise callbacks are always called in the strict order they are placed in the event queue; async callbacks aren't.
-- Async callbacks lose full control of how the function will be executed when passed to a third-party library.
-
-### Browser compatibility
-
-Really good general support, although the exact support for callbacks in APIs depends on the particular API. Refer to the reference documentation for the API you're using for more specific support info.
-
-### Further information
-
-- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing), in particular [Async callbacks](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#async_callbacks)
-
-## setTimeout()
-
-[`setTimeout()`](/en-US/docs/Web/API/setTimeout) is a method that allows you to run a function after an arbitrary amount of time has passed.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------------ | ------------------------------ | -------------------------------- |
-| Yes | Yes (recursive timeouts) | Yes (nested timeouts) | No |
-
-### Code example
-
-Here the browser will wait two seconds before executing the anonymous function, then will display the alert message ([see it running live](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html), and [see the source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html)):
-
-```js
-let myGreeting = setTimeout(function() {
- alert('Hello, Mr. Universe!');
-}, 2000)
-```
-
-### Pitfalls
-
-You can use recursive `setTimeout()` calls to run a function repeatedly in a similar fashion to `setInterval()`, using code like this:
-
-```js
-let i = 1;
-setTimeout(function run() {
- console.log(i);
- i++;
-
- setTimeout(run, 100);
-}, 100);
-```
-
-There is a difference between recursive `setTimeout()` and `setInterval()`:
-
-- Recursive `setTimeout()` guarantees at least the specified amount of time (100ms in this example) will elapse between the executions; the code will run and then wait 100 milliseconds before it runs again. The interval will be the same regardless of how long the code takes to run.
-- With `setInterval()`, the interval we choose _includes_ the time taken to execute the code we want to run in. Let's say that the code takes 40 milliseconds to run — the interval then ends up being only 60 milliseconds.
-
-When your code has the potential to take longer to run than the time interval you've assigned, it's better to use recursive `setTimeout()` — this will keep the time interval constant between executions regardless of how long the code takes to execute, and you won't get errors.
-
-### Browser compatibility
-
-{{Compat("api.setTimeout")}}
-
-### Further information
-
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals), in particular [setTimeout()]()
-- [setTimeout() reference](/en-US/docs/Web/API/setTimeout)
-
-## setInterval()
-
-[`setInterval()`](/en-US/docs/Web/API/setInterval) is a method that allows you to run a function repeatedly with a set interval of time between each execution. Not as efficient as [`requestAnimationFrame()`](/en-US/docs/Web/API/window/requestAnimationFrame), but allows you to choose a running rate/frame rate.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------- | ------------------------------ | -------------------------------- |
-| No | Yes | No (unless they are the same) | No |
-
-### Code example
-
-The following function creates a new [`Date()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object, extracts a time string out of it using [`toLocaleTimeString()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString), and then displays it in the UI. We then run it once per second using `setInterval()`, creating the effect of a digital clock that updates once per second ([see this live](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html), and also [see the source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html)):
-
-```js
-function displayTime() {
- let date = new Date();
- let time = date.toLocaleTimeString();
- document.querySelector('.clock').textContent = time;
-}
-
-displayTime();
-const createClock = setInterval(displayTime, 1000);
-```
-
-### Pitfalls
-
-- The frame rate isn't optimized for the system the animation is running on, and can be somewhat inefficient. Unless you need to choose a specific (slower) framerate, it is generally better to use `requestAnimationFrame()`.
-
-### Browser compatibility
-
-{{Compat("api.setInterval")}}
-
-### Further information
-
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals), in particular [setInterval()](/en-US/docs/Web/API/setInterval)
-- [setInterval() reference](/en-US/docs/Web/API/setInterval)
-
-## requestAnimationFrame()
-
-[`requestAnimationFrame()`](/en-US/docs/Web/API/window/requestAnimationFrame) is a method that allows you to run a function repeatedly, and efficiently, at the best framerate available given the current browser/system. You should, if at all possible, use this instead of `setInterval()`/recursive `setTimeout()`, unless you need a specific framerate.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------- | ------------------------------ | -------------------------------- |
-| No | Yes | No (unless it is the same one) | No |
-
-### Code example
-
-A simple animated spinner; you can find this [example live on GitHub](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html) (see the [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html) also):
-
-```js
-const spinner = document.querySelector('div');
-let rotateCount = 0;
-let startTime = null;
-let rAF;
-
-function draw(timestamp) {
- if(!startTime) {
- startTime = timestamp;
- }
-
- rotateCount = (timestamp - startTime) / 3;
-
- if(rotateCount > 359) {
- rotateCount %= 360;
- }
-
- spinner.style.transform = 'rotate(' + rotateCount + 'deg)';
-
- rAF = requestAnimationFrame(draw);
-}
-
-draw();
-```
-
-### Pitfalls
-
-- You can't choose a specific framerate with `requestAnimationFrame()`. If you need to run your animation at a slower framerate, you'll need to use `setInterval()` or recursive `setTimeout()`.
-
-### Browser compatibility
-
-{{Compat("api.Window.requestAnimationFrame")}}
-
-### Further information
-
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals), in particular [requestAnimationFrame()]()
-- [requestAnimationFrame() reference](/en-US/docs/Web/API/window/requestAnimationFrame)
-
-## Promises
-
-[Promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) are a JavaScript feature that allows you to run asynchronous operations and wait until it is definitely complete before running another operation based on its result. Promises are the backbone of modern asynchronous JavaScript.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------- | ------------------------------ | -------------------------------- |
-| No | No | Yes | See `Promise.all()`, below |
-
-### Code example
-
-The following code fetches an image from the server and displays it inside an {{htmlelement("img")}} element; [see it live also](https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch-chained.html), and see also [the source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html):
-
-```js
-// Call the fetch() method to fetch the image, and store it in a variable
-fetch('coffee.jpg')
-// Use a then() block to respond to the promise's successful completion
-// by taking the returned response and running blob() on it to transform it into a blob
-// blob() also returns a promise; when it successfully completes it returns
-// the blob object in the callback
-.then(response => {
- // The promise fetch() does NOT reject on HTTP errors,
- // so we need to check the boolean Response.ok and throw manually a new Error()
- // for the promise2 to be rejected (for example when a 404 occurs).
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- } else {
- return response.blob();
- }
-})
-.then(myBlob => {
- // Create an object URL that points to the blob object
- let objectURL = URL.createObjectURL(myBlob);
- // Create an element to display the blob (it's an image)
- let image = document.createElement('img');
- // Set the src of the to the object URL so the image displays it
- image.src = objectURL;
- // Append the element to the DOM
- document.body.appendChild(image);
-})
-// If there is a problem, log a useful error message to the console
-.catch(e => {
- console.log('There has been a problem with your fetch operation: ' + e.message);
-});
-```
-
-### Pitfalls
-
-Promise chains can be complex and hard to parse. If you nest a number of promises, you can end up with similar troubles to callback hell. For example:
-
-```js
-remotedb.allDocs({
- include_docs: true,
- attachments: true
-}).then(function (result) {
- let docs = result.rows;
- docs.forEach(function(element) {
- localdb.put(element.doc).then(function(response) {
- alert("Pulled doc with id " + element.doc._id + " and added to local db.");
- }).catch(function (err) {
- if (err.name == 'conflict') {
- localdb.get(element.doc._id).then(function (resp) {
- localdb.remove(resp._id, resp._rev).then(function (resp) {
-// et cetera...
-```
-
-It is better to use the chaining power of promises to go with a flatter, easier to parse structure:
-
-```js
-remotedb.allDocs(...).then(function (resultOfAllDocs) {
- return localdb.put(...);
-}).then(function (resultOfPut) {
- return localdb.get(...);
-}).then(function (resultOfGet) {
- return localdb.put(...);
-}).catch(function (err) {
- console.log(err);
-});
-```
-
-or even:
-
-```js
-remotedb.allDocs(...)
-.then(resultOfAllDocs => {
- return localdb.put(...);
-})
-.then(resultOfPut => {
- return localdb.get(...);
-})
-.then(resultOfGet => {
- return localdb.put(...);
-})
-.catch(err => console.log(err));
-```
-
-That covers a lot of the basics. For a much more complete treatment, see the excellent [We have a problem with promises](https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html) by Nolan Lawson.
-
-### Browser compatibility
-
-{{Compat("javascript.builtins.Promise")}}
-
-### Further information
-
-- [Graceful asynchronous programming with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
-- [Using promises](/en-US/docs/Web/JavaScript/Guide/Using_promises)
-- [Promise reference](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
-
-## Promise.all()
-
-A JavaScript feature that allows you to wait for multiple promises to complete before then running a further operation based on the results of all the other promises.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------- | ------------------------------ | -------------------------------- |
-| No | No | No | Yes |
-
-### Code example
-
-The following example fetches several resources from the server, and uses `Promise.all()` to wait for all of them to be available before then displaying all of them — [see it live](https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html), and see the [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html):
-
-```js
-function fetchAndDecode(url, type) {
- // Returning the top level promise, so the result of the entire chain is returned out of the function
- return fetch(url).then(response => {
- // Depending on what type of file is being fetched, use the relevant function to decode its contents
- if(type === 'blob') {
- return response.blob();
- } else if(type === 'text') {
- return response.text();
- }
- })
- .catch(e => {
- console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message);
- });
-
-}
-// Call the fetchAndDecode() method to fetch the images and the text, and store their promises in variables
-let coffee = fetchAndDecode('coffee.jpg', 'blob');
-let tea = fetchAndDecode('tea.jpg', 'blob');
-let description = fetchAndDecode('description.txt', 'text');
-
-// Use Promise.all() to run code only when all three function calls have resolved
-Promise.all([coffee, tea, description]).then(values => {
- console.log(values);
- // Store each value returned from the promises in separate variables; create object URLs from the blobs
- let objectURL1 = URL.createObjectURL(values[0]);
- let objectURL2 = URL.createObjectURL(values[1]);
- let descText = values[2];
-
- // Display the images in elements
- let image1 = document.createElement('img');
- let image2 = document.createElement('img');
- image1.src = objectURL1;
- image2.src = objectURL2;
- document.body.appendChild(image1);
- document.body.appendChild(image2);
-
- // Display the text in a paragraph
- let para = document.createElement('p');
- para.textContent = descText;
- document.body.appendChild(para);
-});
-```
-
-### Pitfalls
-
-- If a `Promise.all()` rejects, then one or more of the promises you are feeding into it inside its array parameter must be rejecting, or might not be returning promises at all. You need to check each one to see what they returned.
-
-### Browser compatibility
-
-{{Compat("javascript.builtins.Promise.all")}}
-
-### Further information
-
-- [Running code in response to multiple promises fulfilling](/en-US/docs/Learn/JavaScript/Asynchronous/Promises#running_code_in_response_to_multiple_promises_fulfilling)
-- [Promise.all() reference](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)
-
-## Async/await
-
-Syntactic sugar built on top of promises that allows you to run asynchronous operations using syntax that's more like writing synchronous callback code.
-
-| Single delayed operation | Repeating operation | Multiple sequential operations | Multiple simultaneous operations |
-| ------------------------ | ------------------- | ------------------------------ | ----------------------------------------- |
-| No | No | Yes | Yes (in combination with `Promise.all()`) |
-
-### Code example
-
-The following example is a refactor of the simple promise example we saw earlier that fetches and displays an image, written using async/await ([see it live](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-refactored-fetch.html), and see the [source code](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-refactored-fetch.html)):
-
-```js
-async function myFetch() {
- let response = await fetch('coffee.jpg');
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- } else {
- let myBlob = await response.blob();
- let objectURL = URL.createObjectURL(myBlob);
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
- }
-}
-
-myFetch()
-.catch(e => {
- console.log('There has been a problem with your fetch operation: ' + e.message);
-});
-```
-
-### Pitfalls
-
-- You can't use the `await` operator inside a non-`async` function, or in the top level context of your code. This can sometimes result in an extra function wrapper needing to be created, which can be slightly frustrating in some circumstances, but it is worth it most of the time.
-- Browser support for async/await is not as good as that for promises. If you want to use async/await but are concerned about older browser support, you could consider using the [BabelJS](https://babeljs.io/) library — this allows you to write your applications using the latest JavaScript and let Babel figure out what changes, if any, are needed for your user's browsers.
-
-### Browser compatibility
-
-{{Compat("javascript.statements.async_function")}}
-
-### Further information
-
-- [Making asynchronous programming easier with async and await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)
-- [Async function reference](/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
-- [Await operator reference](/en-US/docs/Web/JavaScript/Reference/Operators/await)
-
-{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}
-
-## In this module
-
-- [General asynchronous programming concepts](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts)
-- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals)
-- [Graceful asynchronous programming with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
-- [Making asynchronous programming easier with async and await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)
-- [Choosing the right approach](/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach)
diff --git a/files/en-us/learn/javascript/asynchronous/concepts/beachball.jpg b/files/en-us/learn/javascript/asynchronous/concepts/beachball.jpg
deleted file mode 100644
index e116b4e8eac0fae..000000000000000
Binary files a/files/en-us/learn/javascript/asynchronous/concepts/beachball.jpg and /dev/null differ
diff --git a/files/en-us/learn/javascript/asynchronous/concepts/index.md b/files/en-us/learn/javascript/asynchronous/concepts/index.md
deleted file mode 100644
index bc3fc71df650cae..000000000000000
--- a/files/en-us/learn/javascript/asynchronous/concepts/index.md
+++ /dev/null
@@ -1,179 +0,0 @@
----
-title: General asynchronous programming concepts
-slug: Learn/JavaScript/Asynchronous/Concepts
-tags:
- - JavaScript
- - Learn
- - Promises
- - Threads
- - asynchronous
- - blocking
----
-{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}
-
-In this article, we'll run through a number of important concepts relating to asynchronous programming, and how this looks in web browsers and JavaScript. You should understand these concepts before working through the other articles in the module.
-
-
-
-
-
Prerequisites:
-
- Basic computer literacy, a reasonable understanding of JavaScript
- fundamentals.
-
-
-
-
Objective:
-
- To understand the basic concepts behind asynchronous programming, and
- how they manifest in web browsers and JavaScript.
-
-
-
-
-
-## Asynchronous?
-
-Normally, a given program's code runs straight along, with only one thing happening at once. If a function relies on the result of another function, it has to wait for the other function to finish and return, and until that happens, the entire program is essentially stopped from the perspective of the user.
-
-Mac users, for example, sometimes experience this as the spinning rainbow-colored cursor (or "beachball" as it is often called). This cursor is how the operating system says "the current program you're using has had to stop and wait for something to finish up, and it's taking so long that I was worried you'd wonder what was going on."
-
-
-
-This is a frustrating experience and isn't a good use of computer processing power — especially in an era in which computers have multiple processor cores available. There's no sense sitting there waiting for something when you could let the other task chug along on another processor core and let you know when it's done. This lets you get other work done in the meantime, which is the basis of **asynchronous programming**. It is up to the programming environment you are using (web browsers, in the case of web development) to provide you with APIs that allow you to run such tasks asynchronously.
-
-## Blocking code
-
-Asynchronous techniques are very useful, particularly in web programming. When a web app runs in a browser and it executes an intensive chunk of code without returning control to the browser, the browser can appear to be frozen. This is called **blocking**; the browser is blocked from continuing to handle user input and perform other tasks until the web app returns control of the processor.
-
-Let's look at a couple of examples that show what we mean by blocking.
-
-In our [simple-sync.html](https://github.com/mdn/learning-area/tree/master/javascript/asynchronous/introducing/simple-sync.html) example ([see it running live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html)), we add a click event listener to a button so that when clicked, it runs a time-consuming operation (calculates 10 million dates then logs the final one to the console) and then adds a paragraph to the DOM:
-
-```js
-const btn = document.querySelector('button');
-btn.addEventListener('click', () => {
- let myDate;
- for(let i = 0; i < 10000000; i++) {
- let date = new Date();
- myDate = date;
- }
-
- console.log(myDate);
-
- let pElem = document.createElement('p');
- pElem.textContent = 'This is a newly-added paragraph.';
- document.body.appendChild(pElem);
-});
-```
-
-When running the example, open your JavaScript console then click the button — you'll notice that the paragraph does not appear until after the dates have finished being calculated and the console message has been logged. The code runs in the order it appears in the source, and the later operation doesn't run till the earlier operation has finished running.
-
-> **Note:** The previous example is very unrealistic. You would never calculate 10 million dates on a real web app! It does, however, serve to give you the basic idea.
-
-In our second example, [simple-sync-ui-blocking.html](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-ui-blocking.html) ([see it live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-ui-blocking.html)), we simulate something slightly more realistic that you might come across on a real page. We block user interactivity with the rendering of the UI. In this example, we have two buttons:
-
-- A "Fill canvas" button that when clicked fills the available {{htmlelement("canvas")}} with 1 million blue circles.
-- A "Click me for alert" button that when clicked shows an alert message.
-
-```js
-function expensiveOperation() {
- for(let i = 0; i < 1000000; i++) {
- ctx.fillStyle = 'rgba(0,0,255, 0.2)';
- ctx.beginPath();
- ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false);
- ctx.fill();
- }
-}
-
-fillBtn.addEventListener('click', expensiveOperation);
-
-alertBtn.addEventListener('click', () =>
- alert('You clicked me!');
-);
-```
-
-If you click the first button and then quickly click the second one, you'll see that the alert does not appear until the circles have finished being rendered. The first operation blocks the second one until it has finished running.
-
-> **Note:** OK, in our case, it is ugly and we are faking the blocking effect, but this is a common problem that developers of real apps fight to mitigate all the time.
-
-Why is this? The answer is because JavaScript, generally speaking, is **single-threaded**. At this point, we need to introduce the concept of **threads**.
-
-## Threads
-
-A **thread** is basically a single process that a program can use to complete tasks. Each thread can only do a single task at once:
-
-```
-Task A --> Task B --> Task C
-```
-
-Each task will be run sequentially; a task has to complete before the next one can be started.
-
-As we said earlier, many computers now have multiple cores, so can do multiple things at once. Programming languages that can support multiple threads can use multiple cores to complete multiple tasks simultaneously:
-
-```
-Thread 1: Task A --> Task B
-Thread 2: Task C --> Task D
-```
-
-### JavaScript is single-threaded
-
-JavaScript is traditionally single-threaded. Even with multiple cores, you could only get it to run tasks on a single thread, called the **main thread**. Our example from above is run like this:
-
-```
-Main thread: Render circles to canvas --> Display alert()
-```
-
-After some time, JavaScript gained some tools to help with such problems. [Web workers](/en-US/docs/Web/API/Web_Workers_API) allow you to send some of the JavaScript processing off to a separate thread, called a worker so that you can run multiple JavaScript chunks simultaneously. You'd generally use a worker to run expensive processes off the main thread so that user interaction is not blocked.
-
-```
- Main thread: Task A --> Task C
-Worker thread: Expensive task B
-```
-
-With this in mind, have a look at [simple-sync-worker.html](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-worker.html) ([see it running live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-worker.html)), again with your browser's JavaScript console open. This is a rewrite of our previous example that calculates the 10 million dates, but this time we're using a worker for the calculation. You can see the worker's code here: [worker.js](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/worker.js). Now when you click the button, the browser is able to display the paragraph before the dates have finished calculating. Once the worker has finished calculating, it logs the final date to the console. The first operation no longer blocks the second.
-
-## Asynchronous code
-
-Web workers are pretty useful, but they do have their limitations. A major one is they are not able to access the {{Glossary("DOM")}} — you can't get a worker to directly do anything to update the UI. We couldn't render our 1 million blue circles inside our worker; it can basically just do the number crunching.
-
-The second problem is that although code run in a worker is not blocking, it is still basically synchronous. This becomes a problem when a function relies on the results of multiple previous processes to function. Consider the following thread diagrams:
-
-```
-Main thread: Task A --> Task B
-```
-
-In this case, let's say Task A is doing something like fetching an image from the server and Task B then does something to the image like applying a filter to it. If you start running Task A and then immediately try to run Task B, you'll get an error, because the image won't be available yet.
-
-```
- Main thread: Task A --> Task B --> |Task D|
-Worker thread: Task C -----------> | |
-```
-
-In this case, let's say Task D makes use of the results of both Task B and Task C. If we can guarantee that these results will both be available at the same time, then we might be OK, but this is unlikely. If Task D tries to run when one of its inputs is not yet available, it will throw an error.
-
-To fix such problems, browsers allow us to run certain operations asynchronously. Features like [Promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) allow you to set an operation running (e.g. the fetching of an image from the server), and then wait until the result has returned before running another operation:
-
-```
-Main thread: Task A Task B
- Promise: |__async operation__|
-```
-
-Since the operation is happening somewhere else, the main thread is not blocked while the async operation is being processed.
-
-We'll start to look at how we can write asynchronous code in the next article. Exciting stuff, huh? Keep reading!
-
-## Conclusion
-
-Modern software design increasingly revolves around using asynchronous programming, to allow programs to do more than one thing at a time. As you use newer and more powerful APIs, you'll find more cases where the only way to do things is asynchronously. It used to be hard to write asynchronous code. It still takes getting used to, but it's gotten a lot easier. In the rest of this module, we'll explore further why asynchronous code matters and how to design code that avoids some of the problems described above.
-
-{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}
-
-## In this module
-
-- [General asynchronous programming concepts](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts)
-- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals)
-- [Graceful asynchronous programming with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
-- [Making asynchronous programming easier with async and await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)
-- [Choosing the right approach](/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach)
diff --git a/files/en-us/learn/javascript/asynchronous/implementing_a_promise-based_api/index.md b/files/en-us/learn/javascript/asynchronous/implementing_a_promise-based_api/index.md
new file mode 100644
index 000000000000000..f9a0e3650277102
--- /dev/null
+++ b/files/en-us/learn/javascript/asynchronous/implementing_a_promise-based_api/index.md
@@ -0,0 +1,225 @@
+---
+title: How to implement a promise-based API
+slug: Learn/JavaScript/Asynchronous/Implementing_a_promise-based_API
+tags:
+ - JavaScript
+ - Learn
+---
+{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Introducing_workers", "Learn/JavaScript/Asynchronous")}}
+
+In the last article we discussed how to use APIs that return promises. In this article we'll look at the other side — how to _implement_ APIs that return promises. This is a much less common task than using promise-based APIs, but it's still worth knowing about.
+
+
+
+
+
Prerequisites:
+
+ Basic computer literacy, a reasonable understanding of JavaScript
+ fundamentals, including event handling and the basics of promises.
+
+
+
+
Objective:
+
To understand how implement promise-based APIs.
+
+
+
+
+Generally, when you implement a promise-based API, you'll be wrapping an asynchronous operation, which might use events, or plain callbacks, or a message-passing model. You'll arrange for a `Promise` object to handle the success or failure of that operation properly.
+
+## Implementing an alarm() API
+
+In this example we'll implement a promise-based alarm API, called `alarm()`. It will take as arguments the name of the person to wake up and a delay in milliseconds to wait before waking the person up. After the delay, the function will send a "Wake up!" message, including the name of the person we need to wake up.
+
+### Wrapping setTimeout()
+
+We'll use the {{domxref("setTimeout()")}} API to implement our `alarm()` function. The `setTimeout()` API takes as arguments a callback function and a delay, given in milliseconds. When `setTimeout()` is called, it starts a timer set to the given delay, and when the time expires, it calls the given function.
+
+In the example below, we call `setTimeout()` with a callback function and a delay of 1000 milliseconds:
+
+```html
+
+
+```
+
+```css hidden
+div {
+ margin: .5rem 0;
+}
+```
+
+```js
+const output = document.querySelector('#output');
+const button = document.querySelector('#set-alarm');
+
+function setAlarm() {
+ window.setTimeout(() => {
+ output.textContent = 'Wake up!';
+ }, 1000);
+}
+
+button.addEventListener('click', setAlarm);
+```
+
+{{EmbedLiveSample("Wrapping setTimeout()", 600, 100)}}
+
+### The Promise() constructor
+
+Our `alarm()` function will return a `Promise` that is fulfilled when the timer expires. It will pass a "Wake up!" message into the `then()` handler, and will reject the promise if the caller supplies a negative delay value.
+
+The key component here is the {{jsxref("Promise/Promise", "Promise()")}} constructor. The `Promise()` constructor takes a single function as an argument. We'll call this function the `executor`. When you create a new promise you supply the implementation of the executor.
+
+This executor function itself takes two arguments, which are both also functions, and which are conventionally called `resolve` and `reject`. In your executor implementation, you call the underlying asynchronous function. If the asynchronous function succeeds, you call `resolve`, and if it fails, you call `reject`. If the executor function throws an error, `reject` is called automatically. You can pass a single parameter of any type into `resolve` and `reject`.
+
+So we can implement `alarm()` like this:
+
+```js
+function alarm(person, delay) {
+ return new Promise((resolve, reject) => {
+ if (delay < 0) {
+ throw new Error('Alarm delay must not be negative');
+ }
+ window.setTimeout(() => {
+ resolve(`Wake up, ${person}!`);
+ }, delay);
+ });
+}
+```
+
+This function creates and returns a new `Promise`. Inside the executor for the promise, we:
+
+* check that `delay` is not negative, and throw an error if it is.
+
+* call `window.setTimeout()`, passing a callback and `delay`. The callback will be called when the timer expires, and in the callback we call `resolve`, passing in our `"Wake up!"` message.
+
+## Using the alarm() API
+
+This part should be quite familiar from the last article. We can call `alarm()`, and on the returned promise call `then()` and `catch()` to set handlers for promise fulfillment and rejection.
+
+```html hidden
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css hidden
+button {
+ display: block;
+}
+
+div, button {
+ margin: .5rem 0;
+}
+```
+
+```js
+const name = document.querySelector('#name');
+const delay = document.querySelector('#delay');
+const button = document.querySelector('#set-alarm');
+const output = document.querySelector('#output');
+
+function alarm(person, delay) {
+ return new Promise((resolve, reject) => {
+ if (delay < 0) {
+ throw new Error('Alarm delay must not be negative');
+ }
+ window.setTimeout(() => {
+ resolve(`Wake up, ${person}!`);
+ }, delay);
+ });
+}
+
+button.addEventListener('click', () => {
+ alarm(name.value, delay.value)
+ .then(message => output.textContent = message)
+ .catch(error => output.textContent = `Couldn't set alarm: ${error}`);
+});
+```
+
+{{EmbedLiveSample("Using the alarm() API", 600, 160)}}
+
+Try setting different values for "Name" and "Delay". Try setting a negative value for "Delay".
+
+## Using async and await with the alarm() API
+
+Since `alarm()` returns a `Promise`, we can do everything with it that we could do with any other promise: promise chaining, `Promise.all()`, and `async` / `await`:
+
+
+```html hidden
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css hidden
+button {
+ display: block;
+}
+
+div, button {
+ margin: .5rem 0;
+}
+```
+
+```js
+const name = document.querySelector('#name');
+const delay = document.querySelector('#delay');
+const button = document.querySelector('#set-alarm');
+const output = document.querySelector('#output');
+
+function alarm(person, delay) {
+ return new Promise((resolve, reject) => {
+ if (delay < 0) {
+ throw new Error('Alarm delay must not be negative');
+ }
+ window.setTimeout(() => {
+ resolve(`Wake up, ${person}!`);
+ }, delay);
+ });
+}
+
+button.addEventListener('click', async () => {
+ try {
+ const message = await alarm(name.value, delay.value);
+ output.textContent = message;
+ }
+ catch (error) {
+ output.textContent = `Couldn't set alarm: ${error}`;
+ }
+});
+```
+
+{{EmbedLiveSample("Using async and await with the alarm() API", 600, 160)}}
+
+## See also
+
+- [`Promise()` constructor](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise)
+- [Using promises](/en-US/docs/Web/JavaScript/Guide/Using_promises)
+
+{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Introducing_workers", "Learn/JavaScript/Asynchronous")}}
+
+## In this module
+
+- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
+- [How to use promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
+- **Implementing a promise-based API**
+- [Introducing workers](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing_workers)
+- [Assessment: sequencing animations](/en-US/docs/Learn/JavaScript/Asynchronous/Sequencing_animations)
diff --git a/files/en-us/learn/javascript/asynchronous/index.md b/files/en-us/learn/javascript/asynchronous/index.md
index 4061d0fb5e6ea6e..6490d5e8fdd9486 100644
--- a/files/en-us/learn/javascript/asynchronous/index.md
+++ b/files/en-us/learn/javascript/asynchronous/index.md
@@ -33,24 +33,23 @@ In this module we take a look at {{Glossary("asynchronous")}} {{Glossary("JavaSc
Asynchronous JavaScript is a fairly advanced topic, and you are advised to work through [JavaScript first steps](/en-US/docs/Learn/JavaScript/First_steps) and [JavaScript building blocks](/en-US/docs/Learn/JavaScript/Building_blocks) modules before attempting this.
-If you are not familiar with the concept of asynchronous programming, you should definitely start with the [General asynchronous programming concepts](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts) article in this module. If you are, then you can probably skip to the [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing) module.
-
> **Note:** If you are working on a computer/tablet/other device where you don't have the ability to create your own files, you can try out (most of) the code examples in an online coding program such as [JSBin](https://jsbin.com/) or [Glitch](https://glitch.com).
## Guides
-- [General asynchronous programming concepts](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts)
- - : In this article we'll run through a number of important concepts relating to asynchronous programming, and how this looks in web browsers and JavaScript. You should understand these concepts before working through the other articles in the module.
- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
- - : In this article we briefly recap the problems associated with synchronous JavaScript, and take a first look at some of the different asynchronous JavaScript techniques you'll encounter, showing how they can help us solve such problems.
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals)
- - : Here we look at the traditional methods JavaScript has available for running code asynchronously after a set time period has elapsed, or at a regular interval (e.g. a set number of times per second), talk about what they are useful for, and look at their inherent issues.
-- [Handling async operations gracefully with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
- - : Promises are a comparatively new feature of the JavaScript language that allow you to defer further actions until after the previous action has completed, or respond to its failure. This is really useful for setting up a sequence of operations to work correctly. This article shows you how promises work, where you'll see them in use in WebAPIs, and how to write your own.
-- [Making asynchronous programming easier with async and await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)
- - : Promises can be somewhat complex to set up and understand, and so modern browsers have implemented `async` functions and the `await` operator. The former allows standard functions to implicitly behave asynchronously with promises, whereas the latter can be used inside `async` functions to wait for promises before the function continues. This makes chaining promises simpler and easier to read.
-- [Choosing the right approach](/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach)
- - : To finish this module off, we'll consider the different coding techniques and features we've discussed throughout, looking at which ones you should use when, with recommendations and reminders of common pitfalls where appropriate.
+ - : In this article we'll see what **synchronous** and **asynchronous** programming are, why we often need to use asynchronous techniques, how asynchronous functions have historically been implemented in JavaScript, and what their problems are.
+- [How to use promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
+ - : Here we'll introduce promises and show how to use promise-based APIs. We'll also introduce the `async` and `await` keywords.
+- [Implementing a promise-based API](/en-US/docs/Learn/JavaScript/Asynchronous/Implementing_a_promise-based_API)
+ - : This article outlines how to implement your own promise-based API.
+- [Introducing workers](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing_workers)
+ - : Workers enable you to run certain tasks in a separate thread, to keep your main code responsive. In this article we'll rewrite a long-running synchronous function to use a worker.
+
+## Assessments
+
+- [Sequencing animations](/en-US/docs/Learn/JavaScript/Asynchronous/Sequencing_animations)
+ - : The assessment asks you to use promises to play a set of animations in a particular sequence.
## See also
diff --git a/files/en-us/learn/javascript/asynchronous/introducing/index.md b/files/en-us/learn/javascript/asynchronous/introducing/index.md
index e92b984feaca8eb..3fd487d3999c3d6 100644
--- a/files/en-us/learn/javascript/asynchronous/introducing/index.md
+++ b/files/en-us/learn/javascript/asynchronous/introducing/index.md
@@ -2,21 +2,13 @@
title: Introducing asynchronous JavaScript
slug: Learn/JavaScript/Asynchronous/Introducing
tags:
- - Beginner
- - CodingScripting
- - Guide
- - Introducing
- JavaScript
- Learn
- - Promises
- - async
- - asynchronous
- - await
- - callbacks
---
-{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}
-In this article we briefly recap the problems associated with synchronous JavaScript, and take a first look at some of the different asynchronous techniques you'll encounter, showing how they can help us solve such problems.
+{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}
+
+In this article we'll explain what asynchronous programming is, why we need it, and briefly discuss some of the ways asynchronous functions have historically been implemented in JavaScript.
@@ -24,265 +16,321 @@ In this article we briefly recap the problems associated with synchronous JavaSc
Prerequisites:
Basic computer literacy, a reasonable understanding of JavaScript
- fundamentals.
+ fundamentals, including functions and event handlers.
Objective:
- To gain familiarity with what asynchronous JavaScript is, how it differs
- from synchronous JavaScript, and what use cases it has.
+ To gain familiarity with what asynchronous JavaScript is, how it differs from synchronous JavaScript, and why we need it.
-## Synchronous JavaScript
-
-To allow us to understand what **{{Glossary("asynchronous")}}** JavaScript is, we ought to start off by making sure we understand what **{{Glossary("synchronous")}}** JavaScript is. This section recaps some of the information we saw in the previous article.
-
-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 ([see it live here](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html), and [see the source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html)):
-
-```js
-const btn = document.querySelector('button');
-btn.addEventListener('click', () => {
- alert('You clicked me!');
+Asynchronous programming is a technique that enables your program to start a potentially long-running task, and then rather than having to wait until that task has finished, to be able to continue to be responsive to other events while the task runs. Once the task is completed, your program is presented with the result.
- let pElem = document.createElement('p');
- pElem.textContent = 'This is a newly-added paragraph.';
- document.body.appendChild(pElem);
-});
-```
+Many functions provided by browsers, and especially the most interesting ones, can potentially take a long time, and are therefore asynchronous. For example:
-In this block, the lines are executed one after the other:
+- making HTTP requests with {{domxref("fetch", "fetch()")}}
+- accessing the user's camera or microphone with {{domxref("MediaDevices/getUserMedia", "getUserMedia()")}}
+- asking the user to select files for you to access using {{domxref("window/showOpenFilePicker", "showOpenFilePicker()")}}
-1. We grab a reference to a {{htmlelement("button")}} element that is already available in the DOM.
-2. We add a [`click`](/en-US/docs/Web/API/Element/click_event) event listener to it so that when the button is clicked:
+So even though you may not have to _implement_ your own asynchronous functions very often, you are very likely to need to _use_ them correctly.
- 1. An [`alert()`](/en-US/docs/Web/API/Window/alert) message appears.
- 2. Once the alert is dismissed, we create a {{htmlelement("p")}} element.
- 3. We then give it some text content.
- 4. Finally, we append the paragraph to the document body.
+In this article, we'll start by looking at the problem with long-running synchronous functions, which make asynchronous programming a necessity.
-While each operation is being processed, nothing else can happen — rendering is paused. This is because as we said in the [previous article](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing), [JavaScript is single threaded](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts#javascript_is_single_threaded). Only one thing can happen at a time, on a single main thread, and everything else is blocked until an operation completes.
+## Synchronous programming
-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:
+Consider the following code:
-```html hidden
-
+```js
+const name = 'Miriam';
+const greeting = `Hello, my name is ${name}!`;
+console.log(greeting);
+// "Hello, my name is Miriam!"
```
-{{EmbedLiveSample('Synchronous_JavaScript', '100%', '110px')}}
-
-> **Note:** It is important to remember that [`alert()`](/en-US/docs/Web/API/Window/alert), while being very useful for demonstrating a synchronous blocking operation, is terrible for use in real world applications.
+This code:
-## Asynchronous JavaScript
+1. declares a string called `name`
+2. declares another string called `greeting`, that uses `name`
+3. logs the greeting to the JavaScript console.
-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.
+What we should note here is that the browser effectively steps through the program one line at a time, in the order we wrote it, and at each point it waits for the line to finish its work, before going on to the next line. It has to do this, because each line depends on the work that was done in the preceding lines.
-Why is this difficult to get to work using asynchronous 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:
+That makes this a **synchronous program**. It would still be synchronous if we called out to a separate function, like this:
```js
-let response = fetch('myImage.png'); // fetch is asynchronous
-let blob = response.blob();
-// display your image blob in the UI somehow
+function makeGreeting(name) {
+ return `Hello, my name is ${name}!`;
+}
+
+const name = 'Miriam';
+const greeting = makeGreeting(name);
+console.log(greeting);
+// "Hello, my name is Miriam!"
```
-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 `response` is not yet available. Instead, you need your code to wait until the `response` is returned before it tries to do anything else to it.
+Here `makeGreeting()` is a **synchronous function**, because the caller has to wait for the function to finish its work before the function returns.
-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.
+### A long-running synchronous function
-## Async callbacks
+What if the synchronous function takes a long time?
-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.
+This program generates a number of large prime numbers, using a very inefficient algorithm, when the user clicks the "Generate primes" button. You can control the number of primes to generate, which of course affects how long the operation will take.
-An example of an async callback is the second parameter of the {{domxref("EventTarget.addEventListener", "addEventListener()")}} method (as we saw in action above):
+```html
+
+
+
+
+
+
+
+```
```js
-btn.addEventListener('click', () => {
- alert('You clicked me!');
+function generatePrimes(quota) {
+
+ function isPrime(n) {
+ for (let c = 2; c <= Math.sqrt(n); ++c) {
+ if (n % c === 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ const primes = [];
+ const maximum = 1000000;
+
+ while (primes.length < quota) {
+ const candidate = Math.floor(Math.random() * (maximum + 1));
+ if (isPrime(candidate)) {
+ primes.push(candidate);
+ }
+ }
+
+ return primes;
+}
+
+document.querySelector('#generate').addEventListener('click', () => {
+ const quota = document.querySelector('#quota').value;
+ const primes = generatePrimes(quota);
+ document.querySelector('#output').textContent = `Finished generating ${quota} primes!`;
+});
- let pElem = document.createElement('p');
- pElem.textContent = 'This is a newly-added paragraph.';
- document.body.appendChild(pElem);
+document.querySelector('#reload').addEventListener('click', () => {
+ document.location.reload()
});
```
-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.
+{{EmbedLiveSample("A long-running synchronous function", 600, 120)}}
-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 **not** 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.
+Try clicking "Generate primes". Depending on how fast your computer is, it will probably take a few seconds before the program displays the "Finished!" message.
-You can write your own function containing a callback easily enough. Let's look at another example that loads a resource via the [`XMLHttpRequest` API](/en-US/docs/Web/API/XMLHttpRequest) ([run it live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html), and [see the source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html)):
+### The trouble with long-running synchronous functions
-```js
-function loadAsset(url, type, callback) {
- let xhr = new XMLHttpRequest();
- xhr.open('GET', url);
- xhr.responseType = type;
+The next example is just like the last one, except we added a text box for you to type in. This time, try clicking "Generate primes", then typing in the text box.
- xhr.onload = function() {
- callback(xhr.response);
- };
+You'll find that while our `generatePrimes()` function is running, our program is completely unresponsive: the user can't type anything, or click anything, or do anything else.
- xhr.send();
-}
+```html hidden
+
+
-function displayImage(blob) {
- let objectURL = URL.createObjectURL(blob);
+
+
- let image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
-}
+
-loadAsset('coffee.jpg', 'blob', displayImage);
-```
+
-Here we create a `displayImage()` 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 ``. However, we then create a `loadAsset()` function that takes a callback as a parameter, along with a URL to fetch and a content type. It uses `XMLHttpRequest` (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 [`onload`](/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload) event handler) before it passes it to the callback.
+```
-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 `processJSON()`, `displayText()`, etc.
+```css hidden
+textarea {
+ display: block;
+ margin: 1rem 0;
+}
+```
-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 ([see it live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html), and [the source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html)):
+```js hidden
+function generatePrimes(quota) {
+
+ function isPrime(n) {
+ for (let c = 2; c <= Math.sqrt(n); ++c) {
+ if (n % c === 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ const primes = [];
+ const maximum = 1000000;
+
+ while (primes.length < quota) {
+ const candidate = Math.floor(Math.random() * (maximum + 1));
+ if (isPrime(candidate)) {
+ primes.push(candidate);
+ }
+ }
+
+ return primes;
+}
-```js
-const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
+document.querySelector('#generate').addEventListener('click', () => {
+ const quota = document.querySelector('#quota').value;
+ const primes = generatePrimes(quota);
+ document.querySelector('#output').textContent = `Finished generating ${quota} primes!`;
+});
-gods.forEach(function (eachName, index){
- console.log(index + '. ' + eachName);
+document.querySelector('#reload').addEventListener('click', () => {
+ document.querySelector('#user-input').value = 'Try typing in here immediately after pressing "Generate primes"';
+ document.location.reload();
});
```
-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 `forEach()` 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.
+{{EmbedLiveSample("The trouble with long-running synchronous functions", 600, 200)}}
-## Promises
+This is the basic problem with long-running synchronous functions. What we would like here is a way that our program can:
-Promises are the new style of async code that you'll see used in modern Web APIs. A good example is the [`fetch()`](/en-US/docs/Web/API/fetch) API, which is basically like a modern, more efficient version of {{domxref("XMLHttpRequest")}}. Let's look at a quick example, from our [Fetching data from the server](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data) article:
+- start a long-running operation by calling a function
+- have the function start the operation and return right away, so our program can still be responsive to other events
+- be notified with the result of the operation, when it eventually completes.
-```js
-fetch('products.json').then(function(response) {
- return response.json();
-}).then(function(json) {
- let products = json;
- initialize(products);
-}).catch(function(err) {
- console.log('Fetch problem: ' + err.message);
-});
-```
+That's what an asynchronous function offers us, and the rest of this module explains how they are implemented in JavaScript.
-> **Note:** You can find the finished version on GitHub ([see the source here](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js), and also [see it running live](https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/)).
+## Event handlers
-Here we see `fetch()` taking a single parameter — the URL of a resource you want to fetch from the network — and returning a [promise](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). 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."
+The description we just saw of asynchronous functions might remind you of event handlers, and if it does, you'd be right. Event handlers are really a form of asynchronous programming: you provide a function (the event handler) that will be called, not right away, but whenever the event happens. If "the event" is "the asynchronous operation has completed", then you could see how an event could be used to notify the caller about the result of an asynchronous function call.
-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 `fetch()`:
+Some early asynchronous APIs used events in just this way. The {{domxref("XMLHttpRequest")}} API enables you to make HTTP requests to a remote server using JavaScript. Since this can take a long time, it's an asynchronous API, and you get notified about the progress and eventual completion of a request by attaching event listeners to the `XMLHttpRequest` object.
-- Two [`then()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) 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 `.then()` block returns another promise, meaning that you can chain multiple `.then()` blocks onto each other, so multiple asynchronous operations can be made to run in order, one after another.
-- The [`catch()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) block at the end runs if any of the `.then()` blocks fail — in a similar way to synchronous [`try...catch`](/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) blocks, an error object is made available inside the `catch()`, which can be used to report the kind of error that has occurred. Note however that synchronous `try...catch` won't work with promises, although it will work with [async/await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await), as you'll learn later on.
+The following example shows this in action. Press "Click to start request" to send a request. We create a new {{domxref("XMLHttpRequest")}} and listen for its {{domxref("XMLHttpRequest/loadend_event", "loadend")}} event. The handler logs a "Finished!" message along with the status code.
-> **Note:** 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.
+After adding the event listener we send the request. Note that after this, we can log "Started XHR request": that is, our program can continue to run while the request is going on, and our event handler will be called when the request is complete.
-### The event queue
+```html
+
+
-Async operations like promises are put into an **event queue**, which runs after the main thread has finished processing so that they _do not block_ subsequent JavaScript code from running. The queued operations will complete as soon as possible then return their results to the JavaScript environment.
+
+```
-### Promises versus callbacks
+```css hidden
+pre {
+ display: block;
+ margin: 1rem 0;
+}
+```
-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.
+```js
+const log = document.querySelector('.event-log');
-However, promises are specifically made for handling async operations, and have many advantages over old-style callbacks:
+document.querySelector('#xhr').addEventListener('click', () => {
+ log.textContent = '';
-- You can chain multiple async operations together using multiple `.then()` 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 [callback hell](http://callbackhell.com/)).
-- Promise callbacks are always called in the strict order they are placed in the event queue.
-- Error handling is much better — all errors are handled by a single `.catch()` block at the end of the block, rather than being individually handled in each level of the "pyramid".
-- 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.
+ const xhr = new XMLHttpRequest();
-## The nature of asynchronous code
+ xhr.addEventListener('loadend', () => {
+ log.textContent = `${log.textContent}Finished with status: ${xhr.status}`;
+ });
-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 ([see it live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html), and [the source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html)). 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.
+ xhr.open('GET', 'https://raw.githubusercontent.com/mdn/content/main/files/en-us/_wikihistory.json');
+ xhr.send();
+ log.textContent = `${log.textContent}Started XHR request\n`;});
-```js
-console.log ('Starting');
-let image;
-
-fetch('coffee.jpg').then((response) => {
- console.log('It worked :)')
- return response.blob();
-}).then((myBlob) => {
- let objectURL = URL.createObjectURL(myBlob);
- image = document.createElement('img');
- image.src = objectURL;
- document.body.appendChild(image);
-}).catch((error) => {
- console.log('There has been a problem with your fetch operation: ' + error.message);
+document.querySelector('#reload').addEventListener('click', () => {
+ log.textContent = '';
+ document.location.reload();
});
-
-console.log ('All done!');
```
-The browser will begin executing the code, see the first `console.log()` statement (`Starting`) and execute it, and then create the `image` variable.
+{{EmbedLiveSample("Event handlers", 600, 120)}}
-It will then move to the next line and begin executing the `fetch()` block but, because `fetch()` executes asynchronously without blocking, code execution continues after the promise-related code, thereby reaching the final `console.log()` statement (`All done!`) and outputting it to the console.
+This is just like the [event handlers we've encountered in a previous module](/en-US/docs/Learn/JavaScript/Building_blocks/Events), except that instead of the event being a user action, like the user clicking a button, the event is a change in some object's state.
-Only once the `fetch()` block has completely finished running and delivering its result through the `.then()` blocks will we finally see the second `console.log()` message (`It worked :)`) appear. So the messages have appeared in a different order to what you might expect:
+## Callbacks
-- Starting
-- All done!
-- It worked :)
+An event handler is a particular type of callback. A callback is just a function that's passed into another function, with the expectation that the callback will be called at the appropriate time. As we just saw: callbacks used to be the main way asynchronous functions were implemented in JavaScript.
-If this confuses you, then consider the following smaller example:
+However, callback-based code can get hard to understand when the callback itself has to call functions that accept a callback. This is a common situation if you need to perform some operation that breaks down into a series of asynchronous functions. For example, consider the following:
```js
-console.log("registering click handler");
-
-button.addEventListener('click', () => {
- console.log("get click");
-});
-
-console.log("all done");
-```
+function doStep1(init) {
+ return init + 1;
+}
-This is very similar in behavior — the first and third `console.log()` 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.
+function doStep2(init) {
+ return init + 2;
+}
-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.
+function doStep3(init) {
+ return init + 3;
+}
-To see this in action, try taking a local copy of [our example](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html), and changing the fourth `console.log()` call to the following:
+function doOperation() {
+ let result = 0;
+ result = doStep1(result);
+ result = doStep2(result);
+ result = doStep3(result);
+ console.log(`result: ${result}`);
+}
-```js
-console.log ('All done! ' + image.src + 'displayed.');
+doOperation();
```
-You should now get an error in your console instead of the third message:
+Here we have a single operation that's split into three steps, where each step depends on the last step. In our example the first step adds 1 to the input, the second adds 2, and the third adds 3. Starting with an input of 0, the end result is 6 (0 + 1 + 2 + 3). As synchronous code this is very straightforward. But what if we implemented the steps using callbacks?
-```
-TypeError: image is undefined; can't access its "src" property
-```
-This is because at the time the browser tries to run the third `console.log()` statement, the `fetch()` block has not finished running so the `image` variable has not been given a value.
-> **Note:** For security reasons, you can't `fetch()` 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 [local webserver](/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server).
+```js
+function doStep1(init, callback) {
+ const result = init + 1;
+ callback(result);
+}
-## Active learning: make it all async!
+function doStep2(init, callback) {
+ const result = init + 2;
+ callback(result);
+}
-To fix the problematic `fetch()` example and make the three `console.log()` statements appear in the desired order, you could make the third `console.log()` statement run async as well. This can be done by moving it inside another `.then()` block chained onto the end of the second one, or by moving it inside the second `then()` block. Try fixing this now.
+function doStep3(init, callback) {
+ const result = init + 3;
+ callback(result);
+}
-> **Note:** If you get stuck, you can [find an answer here](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html) (see it [running live](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html) also). You can also find a lot more information on promises in our [Graceful asynchronous programming with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises) guide, later on in the module.
+function doOperation() {
+ doStep1(0, result1 => {
+ doStep2(result1, result2 => {
+ doStep3(result2, result3 => {
+ console.log(`result: ${result3}`);
+ });
+ });
+ });
-## Conclusion
+}
-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.
+doOperation();
+```
-Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.
+Because we have to call callbacks inside callbacks, we get a deeply nested `doOperation()` function, which is much harder to read and debug. This is sometimes called "callback hell" or the "pyramid of doom" (because the indentation looks like a pyramid on its side).
-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.
+When we nest callbacks like this, it can also get very hard to handle errors: often you have to handle errors at each level of the "pyramid", instead of having error handling once at the top level.
-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 stack and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.
+For these reasons, most modern asynchronous APIs don't use callbacks. Instead, the foundation of asynchronous programming in JavaScript is the {{jsxref("Promise")}}, and that's the subject of the next article.
-{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}
+{{NextMenu("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}
## In this module
-- [General asynchronous programming concepts](/en-US/docs/Learn/JavaScript/Asynchronous/Concepts)
-- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
-- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals)
-- [Graceful asynchronous programming with Promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
-- [Making asynchronous programming easier with async and await](/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)
-- [Choosing the right approach](/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach)
+- **Introducing asynchronous JavaScript**
+- [How to use promises](/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
+- [Implementing a promise-based API](/en-US/docs/Learn/JavaScript/Asynchronous/Implementing_a_promise-based_API)
+- [Introducing workers](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing_workers)
+- [Assessment: sequencing animations](/en-US/docs/Learn/JavaScript/Asynchronous/Sequencing_animations)
diff --git a/files/en-us/learn/javascript/asynchronous/introducing_workers/index.md b/files/en-us/learn/javascript/asynchronous/introducing_workers/index.md
new file mode 100644
index 000000000000000..6c536efb4f39dee
--- /dev/null
+++ b/files/en-us/learn/javascript/asynchronous/introducing_workers/index.md
@@ -0,0 +1,258 @@
+---
+title: Introducing workers
+slug: Learn/JavaScript/Asynchronous/Introducing_workers
+tags:
+ - JavaScript
+ - Learn
+---
+{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Implementing_a_promise-based_API", "Learn/JavaScript/Asynchronous/Sequencing_animations", "Learn/JavaScript/Asynchronous")}}
+
+In this final article in our "Asynchronous JavaScript" module, we'll introduce _workers_, which enable you to run some tasks in a separate {{Glossary("Thread", "thread")}} of execution.
+
+
+
+
+
Prerequisites:
+
+ Basic computer literacy, a reasonable understanding of JavaScript
+ fundamentals, including event handling.
+
+
+
+
Objective:
+
To understand how to use web workers.
+
+
+
+
+In the first article of this module, we saw what happens when you have a long-running synchronous task in your program — the whole window becomes totally unresponsive. Fundamentally, the reason for this is that the program is _single-threaded_. A _thread_ is a sequence of instructions that a program follows. Because the program consists of a single thread, it can only do one thing at a time: so if it is waiting for our long-running synchronous call to return, it can't do anything else.
+
+Workers give you the ability to run some tasks in a different thread, so you can start the task, then continue with other processing (such as handling user actions).
+
+But there's a price to pay for this. With multithreaded code, you never know when your thread will be suspended and the other thread will get a chance to run. So if both threads have access to the same variables, it's possible for a variable to change unexpectedly at any time, and this causes bugs that are hard to find.
+
+To avoid these problems in the web, your main code and your worker code never get direct access to each others' variables. Workers and the main code run in completely separate worlds, and only interact by sending each other messages. In particular, this means that workers can't access the DOM (the window, document, page elements, and so on).
+
+There are three different sorts of workers:
+* dedicated workers
+* shared workers
+* service workers
+
+In this article we'll walk through an example of the first sort of worker, then briefly discuss the other two.
+
+## Using web workers
+
+Remember in the first article, where we had a page that calculated prime numbers? We're going to use a worker to run the prime-number calculation, so our page stays responsive to user actions.
+
+### The synchronous prime generator
+
+Let's first take another look at the JavaScript in our previous example:
+
+```js
+function generatePrimes(quota) {
+
+ function isPrime(n) {
+ for (let c = 2; c <= Math.sqrt(n); ++c) {
+ if (n % c === 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ const primes = [];
+ const maximum = 1000000;
+
+ while (primes.length < quota) {
+ const candidate = Math.floor(Math.random() * (maximum + 1));
+ if (isPrime(candidate)) {
+ primes.push(candidate);
+ }
+ }
+
+ return primes;
+}
+
+document.querySelector('#generate').addEventListener('click', () => {
+ const quota = document.querySelector('#quota').value;
+ const primes = generatePrimes(quota);
+ document.querySelector('#output').textContent = `Finished generating ${quota} primes!`;
+});
+
+document.querySelector('#reload').addEventListener('click', () => {
+ document.querySelector('#user-input').value = 'Try typing in here immediately after pressing "Generate primes"';
+ document.location.reload();
+});
+```
+
+In this program, after we call `generatePrimes()`, the program becomes totally unresponsive.
+
+### Prime generation with a worker
+
+For this example, start by making a local copy of the files at . There are four files in this directory:
+
+* index.html
+* style.css
+* main.js
+* generate.js
+
+The "index.html" file and the "style.css" files are already complete:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+textarea {
+ display: block;
+ margin: 1rem 0;
+}
+```
+
+The "main.js" and "generate.js" files are empty. We're going to add the main code to "main.js", and the worker code to "generate.js".
+
+So first, we can see that the worker code is kept in a separate script from the main code. We can also see, looking at "index.html" above, that only the main code is included in a `