ES6 Promiseの原理と利用方法の分析例
1. Promise 之前
1.1 回调函数
回调函数:把函数A当作参数传递给另一个函数B调用,那么A就是回调函数。【推荐:JavaScript视频教程】
一些例子
具名回调
function 你有几只狗(fn){ fn('一只狗') }function 数狗(数量){ console.log(数量) } 你有几只狗(数狗) // 一只狗
匿名回调
function 你有几只狗(fn){ fn('一只狗') } 你有几只狗(function(数量){console.log(数量) }) // 一只狗
常见的例子
jQuery中使用回调函数,这里用的是匿名回调的方式
$("#btn").click(function(){ console.log('点到我了') })
1.2 回调地狱(回调缺点1)
回调地狱:指的是回调嵌套过多的情况,导致代码很难被看懂。
let info = []function 你有几只狗(fn){ fn('一只狗') }function 你有几只猫(fn){ fn('一只猫') }function 知道了(数量,callback){ info.push(数量) console.log(info) if(callback){ callback() } }// 开始调用 如果比这再多几层,就不容易看懂了你有几只狗(function(狗数){ console.log(狗数) 知道了(狗数, function(){ 你有几只猫(function(猫数){ console.log(猫数) 知道了(猫数) }) }) })
1.3 不使用Promise,如何解决
利用具名函数代替匿名函数
let info = []function 你有几只狗(fn){ fn('一只狗') }function 你有几只猫(fn){ fn('一只猫') }function 知道了(数量,callback){ info.push(数量) console.log(info) if(callback){ callback() } }function 告诉你猫的个数(猫数){ console.log(猫数) 知道了(猫数) }function 继续数(){ 你有几只猫(告诉你猫的个数) }function 告诉你狗的个数(狗数){ console.log(狗数) 知道了(狗数, 继续数) } 你有几只狗(告诉你狗的个数) // 好像也没好到哪去。。。
1.4 回调方式各不相同,需要单独记忆(回调缺点2)
readFile('C:\\1.txt',function (error, data) { // node.js 读取文件方法中的回调 if(error) { console.log('成功') console.log(data.toString()) } else { console.log('读取文件失败') } }) $.ajax({ // jQuery中ajax方法中的回调 url:'/2.txt' success: function(response) { console.log('成功') }, error: function(){ console.log('失败') } })
2. Promise 的目的
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
3. Promise 的原理
3.1 实现原理
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。通过在函数内部return 一个 Promise对象的实例,这样就可以使用Promise的属性和方法进行下一步操作了。
function 函数名(){ return new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); // 异步操作成功时调用,把结果作为参数传递出去 } else { reject(error); // 异步失败时调用,把错误作为参数传递出去 } }) }
3.2 调用逻辑
S1和E1两个都没有报错,执行S2(resolve执行,系统认为搞定了,没报错)
S1和E1任何一个有报错,执行E2(reject执行,系统认为没搞定,报错了)
4. Promise 的使用
4.1 Promise 的属性与方法
属性
Promise.prototype 表示 Promise 构造器的原型
方法
Promise.prototype.then()
返回一个 Promise 。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。
Promise.prototype.catch()
返回一个Promise,并且处理拒绝的情况。等价于Promise.prototype.then(undefined, onRejected)
Promise.prototype.finally()
finally() 方法返回一个Promise,在执行then()和catch()后,都会执行finally指定的回调函数。避免同样的语句需要在then()和catch()中各写一次的情况。
Promise.all(iterable)
返回一个 Promise 实例,iterable参数内所有的 promise 都resolved后,才回调完成resolve。
Promise.race(iterable)
返回一个 promise ,并伴随着 promise对象解决的返回值或拒绝的错误原因, 只要 iterable 中有一个 promise 对象”解决(resolve)”或”拒绝(reject)”。
Promise.resolve()
返回一个以给定值解析后的Promise对象。但如果这个值是个thenable(即带有then方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态(指resolved/rejected/pending/settled);如果传入的value本身就是promise对象,则该对象作为Promise.resolve方法的返回值返回;否则以该值为成功状态返回promise对象。
Promise.reject()
返回一个带有拒绝原因reason参数的Promise对象。
4.2 将回调地狱中的例子,改写为Promise的形式
可以看到使用 Promise后,逻辑变得非常直观
写得更完整一些
Promise套Promise时,也就是Promise链的时候——注意信息的传递
一个失败的例子,当我们使用Promise链的时候,如果每一步都需要上一步的数据时,就需要传参,成功通过resolve传参,失败通过reject传参,如果忘记传参,就得不到想要的结果。
resolve把成功的数据返回给下一个回调
reject把失败的数据返回给下一个回调。
给这里的resolve传一个参
改成失败的例子
先不给reject传参,如果失败的话,下一个回调拿不到数据
给 reject传参
我们可以看到,即使是走的失败回调,下一个成功回调还是执行了,由于 不知道() 默认返回undefined, 相当于失败已经处理了,在成功和失败都被处理的情况下,下一个回调会执行的。
改成符合预期的,即失败不调用。
失败不调用的简写形式
上述情况执行后 .then(除了狗呢)里面的成功回调没有执行,我们增加一个失败回调看看
同样也可以返回 resolve,让后面成功回调可以执行
4.3 应用
加载图片
将图片的加载写成一个Promise,一旦加载完成,Promise的状态就发生变化。
const preloadImage = function (path) { return new Promise(function (resolve, reject) { const image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }); };
Generator 函数与 Promise 的结合(详情见参考链接,阮一峰的教程)
5. 干掉Promise中的回调
5.1 await
成功的情况
失败的情况
利用 try catch
await 配合 try catch使用,比较完整
6. 总结
能利用Promise对象,把普通函数改成返回Promise的形式,解决回调地狱的问题。
明白Promise的成功失败调用逻辑,可以灵活的进行调整。
理解核心知识,先用起来,慢慢整合吸收知识。
以上がES6 Promiseの原理と利用方法の分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









非同期はes7です。 async と await は ES7 に新しく追加されたもので、非同期操作のソリューションです。async/await は co モジュールとジェネレーター関数の糖衣構文と言え、より明確なセマンティクスで JS 非同期コードを解決します。名前が示すように、async は「非同期」を意味します。async は関数が非同期であることを宣言するために使用されます。async と await の間には厳密な規則があります。両方を互いに分離することはできず、await は async 関数内でのみ記述できます。

ブラウザの互換性のため。 ES6 は JS の新しい仕様として、多くの新しい構文と API を追加していますが、最新のブラウザーは ES6 の新機能を高度にサポートしていないため、ES6 コードを ES5 コードに変換する必要があります。 WeChat Web 開発者ツールでは、デフォルトで babel が使用され、開発者の ES6 構文コードを 3 つの端末すべてで適切にサポートされる ES5 コードに変換し、開発者がさまざまな環境によって引き起こされる開発上の問題を解決できるようにします。プロジェクト内でのみ設定して確認するだけです。 「ES6~ES5」オプション。

日常生活では、約束と履行の間で問題に遭遇することがよくあります。個人的な関係でもビジネス取引でも、約束を守ることが信頼を築く鍵となります。ただし、コミットメントの是非についてはしばしば議論の余地があります。この記事では、約束の長所と短所を検討し、約束を守る方法についていくつかのアドバイスを提供します。約束されたメリットは明らかです。まず、コミットメントは信頼を築きます。人が約束を守るとき、その人は信頼できる人であると他人に信じ込ませます。信頼は人々の間に確立される絆であり、それは人々をより良くすることができます

es5 では、for ステートメントと IndexOf() 関数を使用して配列の重複排除を実現できます。構文 "for(i=0;i<配列長;i++){a=newArr.indexOf(arr[i]);if( a== -1){...}}」。 es6 では、スプレッド演算子 Array.from() および Set を使用して重複を削除できます。まず配列を Set オブジェクトに変換して重複を削除してから、スプレッド演算子または Array.from() 関数を使用する必要があります。 Set オブジェクトを配列に変換してグループ化するだけです。

Vue は人気のあるフロントエンド フレームワークであり、アプリケーションを開発するときにさまざまなエラーや問題に遭遇することがよくあります。このうち、Uncaught(inpromise)TypeError は一般的なエラー タイプです。この記事では、その原因と解決策について説明します。 Uncaught(inpromise)TypeError とは何ですか? Uncaught(inpromise)TypeError エラーは通常、次の場所に表示されます。

es6 では、一時的なデッド ゾーンは構文エラーであり、ブロックを閉じたスコープにする let および const コマンドを指します。コード ブロック内では、let/const コマンドを使用して変数が宣言される前に、変数は使用できず、変数が宣言される前は変数の「デッド ゾーン」に属します。これは構文上「一時デッド ゾーン」と呼ばれます。 ES6 では、一時的なデッド ゾーンや let ステートメントや const ステートメントでは変数のプロモーションが発生しないことを規定しています。これは主に実行時エラーを減らし、変数が宣言される前に使用されて予期しない動作が発生するのを防ぐためです。

Promise.resolve() の詳細な説明には、特定のコード例が必要です。Promise は、非同期操作を処理するための JavaScript のメカニズムです。実際の開発では、順番に実行する必要があるいくつかの非同期タスクを処理する必要があることがよくあり、満たされた Promise オブジェクトを返すために Promise.resolve() メソッドが使用されます。 Promise.resolve() は Promise クラスの静的メソッドであり、

ES6 インポートにより変数が昇格されます。変数ホイスティングとは、変数宣言をそのスコープの先頭に昇格させることです。 js はコンパイルと実行のフェーズを経る必要があります。コンパイル フェーズでは、すべての変数宣言が収集され、変数は事前に宣言され、他のステートメントの順序は変更されません。したがって、コンパイル フェーズでは、最初のステップはすでに2 番目の部分は、ステートメントが実行フェーズで実行された場合にのみ実行されます。
