diff options
Diffstat (limited to 'files/zh-cn/web/javascript/guide/using_promises')
-rw-r--r-- | files/zh-cn/web/javascript/guide/using_promises/index.html | 54 |
1 files changed, 27 insertions, 27 deletions
diff --git a/files/zh-cn/web/javascript/guide/using_promises/index.html b/files/zh-cn/web/javascript/guide/using_promises/index.html index c714260d7f..22a0163216 100644 --- a/files/zh-cn/web/javascript/guide/using_promises/index.html +++ b/files/zh-cn/web/javascript/guide/using_promises/index.html @@ -20,7 +20,7 @@ translation_of: Web/JavaScript/Guide/Using_promises <p>以下为使用 <code>createAudioFileAsync()</code> 的示例:</p> -<pre class="brush: js notranslate">// 成功的回调函数 +<pre class="brush: js">// 成功的回调函数 function successCallback(result) { console.log("音频文件创建成功: " + result); } @@ -36,13 +36,13 @@ createAudioFileAsync(audioSettings, successCallback, failureCallback)</pre> <p>如果函数 <code>createAudioFileAsync()</code> 被重写为返回 Promise 的形式,那么我们可以像下面这样简单地调用它:</p> -<pre class="brush: js line-numbers language-js notranslate">const promise = createAudioFileAsync(audioSettings); +<pre class="brush: js line-numbers language-js">const promise = createAudioFileAsync(audioSettings); promise.then(successCallback, failureCallback); </pre> <p>或者简写为:</p> -<pre class="brush: js line-numbers language-js notranslate">createAudioFileAsync(audioSettings).then(successCallback, failureCallback); +<pre class="brush: js line-numbers language-js">createAudioFileAsync(audioSettings).then(successCallback, failureCallback); </pre> <p>我们把这个称为 <em>异步函数调用</em>,这种形式有若干优点,下面我们将会逐一讨论。</p> @@ -65,13 +65,13 @@ promise.then(successCallback, failureCallback); <p>见证奇迹的时刻:<code>then()</code> 函数会返回一个和原来不同的<strong>新的 Promise</strong>:</p> -<pre class="brush: js line-numbers language-js notranslate">const promise = doSomething(); +<pre class="brush: js line-numbers language-js">const promise = doSomething(); const promise2 = promise.then(successCallback, failureCallback); </pre> <p>或者</p> -<pre class="brush: js notranslate">const promise2 = doSomething().then(successCallback, failureCallback);</pre> +<pre class="brush: js">const promise2 = doSomething().then(successCallback, failureCallback);</pre> <p><code>promise2</code> 不仅表示 <code>doSomething()</code> 函数的完成,也代表了你传入的 <code>successCallback</code> 或者 <code>failureCallback</code> 的完成,这两个函数也可以返回一个 Promise 对象,从而形成另一个异步操作,这样的话,在 <code>promise2</code> 上新增的回调函数会排在这个 Promise 对象的后面。</p> @@ -79,7 +79,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>在过去,要想做多重的异步操作,会导致经典的回调地狱:</p> -<pre class="brush: js notranslate">doSomething(function(result) { +<pre class="brush: js">doSomething(function(result) { doSomethingElse(result, function(newResult) { doThirdThing(newResult, function(finalResult) { console.log('Got the final result: ' + finalResult); @@ -90,7 +90,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>现在,我们可以把回调绑定到返回的 Promise 上,形成一个 Promise 链:</p> -<pre class="brush: js notranslate">doSomething().then(function(result) { +<pre class="brush: js">doSomething().then(function(result) { return doSomethingElse(result); }) .then(function(newResult) { @@ -104,7 +104,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>then 里的参数是可选的,<code>catch(failureCallback)</code> 是 <code>then(null, failureCallback)</code> 的缩略形式。如下所示,我们也可以用<a href="/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数</a>来表示:</p> -<pre class="brush: js notranslate">doSomething() +<pre class="brush: js">doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => { @@ -119,7 +119,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>有可能会在一个回调失败之后继续使用链式操作,即,使用一个 <code>catch</code>,这对于在链式操作中抛出一个失败之后,再次进行新的操作会很有用。请阅读下面的例子:</p> -<pre class="brush: js notranslate">new Promise((resolve, reject) => { +<pre class="brush: js">new Promise((resolve, reject) => { console.log('初始化'); resolve(); @@ -139,7 +139,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>输出结果如下:</p> -<pre class="notranslate">初始化 +<pre>初始化 执行“那个” 执行“这个”,无论前面发生了什么 </pre> @@ -150,7 +150,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>在之前的回调地狱示例中,你可能记得有 3 次 <code>failureCallback</code> 的调用,而在 Promise 链中只有尾部的一次调用。</p> -<pre class="brush: js notranslate">doSomething() +<pre class="brush: js">doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => console.log(`Got the final result: ${finalResult}`)) @@ -160,7 +160,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>通常,一遇到异常抛出,浏览器就会顺着 Promise 链寻找下一个 <code>onRejected</code> 失败回调函数或者由 <code>.catch()</code> 指定的回调函数。这和以下同步代码的工作原理(执行过程)非常相似。</p> -<pre class="brush: js notranslate">try { +<pre class="brush: js">try { let result = syncDoSomething(); let newResult = syncDoSomethingElse(result); let finalResult = syncDoThirdThing(newResult); @@ -172,7 +172,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>在 ECMAScript 2017 标准的 <code><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function">async/await</a></code> 语法糖中,这种异步代码的对称性得到了极致的体现:</p> -<pre class="brush: js notranslate">async function foo() { +<pre class="brush: js">async function foo() { try { const result = await doSomething(); const newResult = await doSomethingElse(result); @@ -204,7 +204,7 @@ const promise2 = promise.then(successCallback, failureCallback); <p>一个特别有用的例子:当你使用 {{Glossary("Node.js")}} 时,有些依赖模块可能会有未被处理的 rejected promises,这些都会在运行时打印到控制台。你可以在自己的代码中捕捉这些信息,然后添加与 {{domxref("Window.unhandledrejection_event", "unhandledrejection")}} 相应的处理函数来做分析和处理,或只是为了让你的输出更整洁。举例如下:</p> -<pre class="brush: js notranslate">window.addEventListener("unhandledrejection", event => { +<pre class="brush: js">window.addEventListener("unhandledrejection", event => { /* 你可以在这里添加一些代码,以便检查 event.promise 中的 promise 和 event.reason 中的 rejection 原因 */ @@ -223,14 +223,14 @@ const promise2 = promise.then(successCallback, failureCallback); <p>理想状态下,所有的异步函数都已经返回 Promise 了。但有一些 API 仍然使用旧方式来传入的成功(或者失败)的回调。典型的例子就是 {{domxref("WindowTimers.setTimeout", "setTimeout()")}} 函数:</p> -<pre class="brush: js notranslate">setTimeout(() => saySomething("10 seconds passed"), 10000); +<pre class="brush: js">setTimeout(() => saySomething("10 seconds passed"), 10000); </pre> <p>混用旧式回调和 Promise 可能会造成运行时序问题。如果 <code>saySomething</code> 函数失败了,或者包含了编程错误,那就没有办法捕获它了。这得怪 <code>setTimeout</code>。</p> <p>幸运地是,我们可以用 Promise 来封装它。最好的做法是,将这些有问题的函数封装起来,留在底层,并且永远不要再直接调用它们:</p> -<pre class="brush: js notranslate">const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); +<pre class="brush: js">const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback); </pre> @@ -245,33 +245,33 @@ wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback); <p>我们可以发起并行操作,然后等多个操作全部结束后进行下一步操作,如下:</p> -<pre class="brush: js notranslate">Promise.all([func1(), func2(), func3()]) +<pre class="brush: js">Promise.all([func1(), func2(), func3()]) .then(([result1, result2, result3]) => { /* use result1, result2 and result3 */ });</pre> <p>可以使用一些聪明的 JavaScript 写法实现时序组合:</p> -<pre class="brush: js notranslate">[func1, func2, func3].reduce((p, f) => p.then(f), Promise.resolve()) +<pre class="brush: js">[func1, func2, func3].reduce((p, f) => p.then(f), Promise.resolve()) .then(result3 => { /* use result3 */ });</pre> <p>通常,我们递归调用一个由异步函数组成的数组时,相当于一个 Promise 链:</p> -<pre class="notranslate"><code>Promise.resolve().then(func1).then(func2).then(func3);</code></pre> +<pre><code>Promise.resolve().then(func1).then(func2).then(func3);</code></pre> <p>我们也可以写成可复用的函数形式,这在函数式编程中极为普遍:</p> -<pre class="brush: js notranslate">const applyAsync = (acc,val) => acc.then(val); +<pre class="brush: js">const applyAsync = (acc,val) => acc.then(val); const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x)); </pre> <p><code>composeAsync()</code> 函数将会接受任意数量的函数作为其参数,并返回一个新的函数,该函数接受一个通过 composition pipeline 传入的初始值。这对我们来说非常有益,因为任一函数可以是异步或同步的,它们能被保证按顺序执行:</p> -<pre class="brush: js notranslate">const transformData = composeAsync(func1, func2, func3); +<pre class="brush: js">const transformData = composeAsync(func1, func2, func3); const result3 = transformData(data); </pre> <p>在 ECMAScript 2017 标准中, 时序组合可以通过使用 <code>async/await</code> 而变得更简单:</p> -<pre class="brush: js notranslate">let result; +<pre class="brush: js">let result; for (const f of [func1, func2, func3]) { result = await f(result); } @@ -281,13 +281,13 @@ for (const f of [func1, func2, func3]) { <p>为了避免意外,即使是一个已经变成 resolve 状态的 Promise,传递给 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code> 的函数也总是会被异步调用:</p> -<pre class="brush: js notranslate">Promise.resolve().then(() => console.log(2)); +<pre class="brush: js">Promise.resolve().then(() => console.log(2)); console.log(1); // 1, 2 </pre> <p>传递到 <code>then()</code> 中的函数被置入到一个微任务队列中,而不是立即执行,这意味着它是在 JavaScript 事件队列的所有运行时结束了,且事件队列被清空之后,才开始执行:</p> -<pre class="brush: js notranslate">const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); +<pre class="brush: js">const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); wait().then(() => console.log(4)); Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); @@ -299,7 +299,7 @@ console.log(1); // 1, 2, 3, 4</pre> <p>嵌套 Promise 是一种可以限制 <code>catch</code> 语句的作用域的控制结构写法。明确来说,嵌套的 <code>catch</code> 仅捕捉在其之前同时还必须是其作用域的 failureres,而捕捉不到在其链式以外或者其嵌套域以外的 error。如果使用正确,那么可以实现高精度的错误修复。</p> -<pre class="brush: js notranslate">doSomethingCritical() +<pre class="brush: js">doSomethingCritical() .then(result => doSomethingOptional() .then(optionalResult => doSomethingExtraNice(optionalResult)) .catch(e => {console.log(e.message)})) // 即使有异常也会忽略,继续运行;(最后会输出) @@ -314,7 +314,7 @@ console.log(1); // 1, 2, 3, 4</pre> <p>在编写 Promise 链时,需要注意以下示例中展示的几个错误:</p> -<pre class="brush: js example-bad notranslate">// 错误示例,包含 3 个问题! +<pre class="brush: js example-bad">// 错误示例,包含 3 个问题! doSomething().then(function(result) { doSomethingElse(result) // 没有返回 Promise 以及没有必要的嵌套 Promise @@ -330,7 +330,7 @@ doSomething().then(function(result) { <p>一个好的经验法则是总是返回或终止 Promise 链,并且一旦你得到一个新的 Promise,返回它。下面是修改后的平面化的代码:</p> -<pre class="brush: js example-good notranslate">doSomething() +<pre class="brush: js example-good">doSomething() .then(function(result) { return doSomethingElse(result); }) |