お約束の体験

promiseそれは何ですか

抽象的な観点から見ると、これは新しいソリューションです。JSは、Solve での非同期プログラミングのソリューションです。古い解決策は、純粋なコールバックです (ただし、promiseコールバック関数も含まれているため、コールバック関数を追加しました)。そのため、コールバック地獄があります。

文法的に言えば、Promiseこれはコンストラクターです。したがって、インスタンス オブジェクトを作成し、そのインスタンス オブジェクトに処理を指示することができます。逆に、一般的な関数であれば、関数自体が何かを行うことになります。

機能の観点:promiseオブジェクトは非同期操作をカプセル化するために使用され、その結果を取得できます。

promiseステータスは次のように変化します。

  1. pendingになるresolved
  2. pendingになるrejected
  • この2州のみ
  • pending初期化状態を示します
  • オブジェクトpromiseは 1 回だけ変更できます
  • 成功しても失敗しても結果データはある
  • 成功した結果データを一般的に と呼びvlaue、失敗した結果データを一般的に と呼びます。reason

promise基本的なプロセスは次のとおりです。

ここに画像の説明を挿入
説明:

  1. 新しいオブジェクトを作成し、promise新しく作成されたオブジェクトpromiseの状態がpeding状態、つまり初期化状態になります。
  2. コンストラクターにpromiseパラメータ (parameter ) を渡し执行器函数执行器函数非同期タスクを実行します。
  3. 非同期タスクの実行は、最終的には成功する場合も失敗する場合もあります。成功した場合はresolve()メソッドが実行され、promiseオブジェクトの状態がresolved状態になり、失敗した場合はreject()メソッドが実行され、promiseオブジェクトの状態がrejected状態になります。
  4. 状態が変化したら、成功または失敗のコールバック関数を呼び出します。
  5. 成功または失敗のコールバック関数が渡される.then.catch指定されます。このうち、.then成功したコールバックと失敗したコールバックの両方を指定できますが、.catch失敗したコールバックのみを指定できます。
  6. 最後に、新しいオブジェクト.thenが返されますpromise

Promise の基本的な使い方:

ここに画像の説明を挿入

なぜ約束するのか

純粋なコールバック: 実際に非同期タスクを実行するときは、コールバック関数を指定する必要があります。つまり、最初にコールバック関数を指定してから非同期タスクを開始する必要があり、次のようになる必要があります之前事先

promiseオブジェクト: 非同期タスクの開始後にコールバック関数を指定できますが、非同期タスクが成功するか結果が得られる前にコールバック関数を指定することもできます。もちろん、非同期タスクの結果が得られた後でもコールバック関数を指定できます。これも純粋なコールバックでは実行できないことです。つまり、純粋なコールバック関数と比較して、promiseオブジェクトはコールバック関数を指定する方法がより柔軟です。

概要:promiseコールバック関数を指定する方法がより柔軟になりました。通常、コールバック関数は非同期タスクの実行後に指定します。

纯回调: 非同期タスクを開始する前に指定する必要があります

Promiseコンストラクター自体は実行関数を受け取りexcutor、実行関数はexcutor2 つの関数 (1 つはresolve関数、もう 1 つはreject関数) を受け取ります。また、executor 関数はexcutor同期コールバック関数であり、実際の非同期コードはexecutor 関数内に記述されますexcutor

Promiseのプロトタイプ オブジェクトにはthen2 つのパラメータを指定するメソッドがonResolved, onRejectedあり、どちらも関数型です。より正確には、これはコールバック関数であり、1 つは成功したコールバックに対応し、もう 1 つは失敗したコールバックに対応します。成功したコールバックは を受け取りvalue、失敗したコールバックは を受け取りreason、新しいpromiseオブジェクトを返します。promiseこれはチェーンコールの前提条件でもあります。

promiseチェーンコールに対応しているので、コールバック地獄の問題も解決できます。

コールバック地獄とは何ですか?

回答: コールバック関数はネストして呼び出され、外部コールバック関数の非同期実行の結果がネストされたコールバック関数の実行条件となります。コールバック ヘルには複数の非同期操作が含まれており、それはシリアルに実行されますタンデム実行とは何ですか? 非同期タスク 1、非同期タスク 2、非同期タスク 3... があり、2 番目の非同期タスクは最初の非同期タスクの結果に条件付けされ、同様に 3 番目の非同期タスクは 2 番目の非同期タスクの結果に条件付けされるとします。このとき、コールバックの入れ子が発生し、コードの編成形式が徐々に右に移動してしまい、読みにくくなります。その場合、例外処理を個別に処理する必要があり、これも処理の難易度が高くなります。このような追従処理が面倒で、読み込まれない状態はコールバック地獄です。

オブジェクトが取得されるたびに、それは非同期タスク、または非同期タスクに対応するpromiseタスクが開始されたことを意味します。promiseその後、.thenコーディング メソッドは同期コーディングと同様に上から下に実行され、ネストされた形式ではなく、コールバック地獄は発生しません。次に、例外を処理する方法では、例外を最後に処理するだけで済みます。つまり、途中で成功した一部のコールバックだけが必要になります。

//2.2. 使用promise的链式调用解决回调地狱
doSomething()
  .then(function(result) {
    
    
  return doSomethingElse(result)
})
  .then(function(newResult) {
    
    
  return doThirdThing(newResult)
})
  .then(function(finalResult) {
    
    
  console.log('Got the final result: ' + finalResult)
})
  .catch(failureCallback)

最後に例外を処理する方法は、例外送信とも呼ばれます。チェーン呼び出しでは、複数のpromiseプロセスがあり、どれに何が起こっても、レイヤーごとに最下位のエラー コールバック処理に渡されます。

概要:promiseコーディングでは処理が上から下に行われるため、読み取りがより便利になり、例外処理もより便利になります。ただし、promiseこれはコールバック地獄を解決するための最適な選択ではありません。promiseコールバックのネストはないものの、依然としてコールバック関数が存在するためです。ただし、asyncと ではawaitコールバック関数は生成されません。

Q: コールバック地獄のデメリットは?

回答: 例外を読むのは簡単ではありません/例外を処理するのは簡単ではありません

Q:解決策は?

答え:promiseチェーンコール

Q:究極の解決策は?

答え: async/await

  1. Promiseコンストラクター: Promise (エクスキューター) {}
    excutorエグゼキューター関数: 同期実行 (解決、拒否) => {}
    resolve関数: 内部定義が成功したときに呼び出す関数 value => {} 関数
    reject: 内部定義が失敗したときに呼び出す関数reason => {}
    注:同期コールバックは内部で実行excutorされPromise、非同期操作はエグゼキューターで実行されます。

  2. Promise.prototype.thenメソッド: (onResolved, onRejected) => {}
    onResolved関数: 成功コールバック関数 (値) => {}
    onRejected関数: 失敗コールバック関数 (理由) => {}
    説明: 成功値を取得するための成功コールバックと失敗理由を取得するための失敗コールバックを指定し、新しい Promise オブジェクトを返します。これはチェーン呼び出しをサポートするための前提条件でもありますpormise

  3. Promise.prototype.catchメソッド: (onRejected) => {}
    onRejected関数: 失敗したコールバック関数 (理由) => {}
    説明:then()糖衣構文、以下と同等:then(undefined, onRejected)

  4. Promise.resolveメソッド: (値) => {}
    値: 成功したデータまたはpromiseオブジェクト説明:本質的に糖衣構文である
    成功/失敗オブジェクトを返します。promise

//二者都返回一个promise
const p1 = new Promise((resolve, reject) => {
    
    
       setTimeout(() => {
    
    
        resolve(1)
       }, 100);
   })
const p2 = Promise.resolve(2)
  1. Promise.rejectメソッド: (reason) => {}
    reason: 失敗の理由
    説明: 失敗した Promise オブジェクトを返します。これは本質的には糖衣構文です。
const p1 = new Promise((resolve, reject) => {
    
    
       setTimeout(() => {
    
    
        reject(1)
       }, 100);
   })
const p3 = Promise.reject(3)
  1. Promise.allメソッド: (約束) => {}
    promises:を含むn配列promise

説明: 新しいものを返しますpromise。すべてがpromise成功した場合のみ成功し、そのうちの 1 つが失敗した場合は直接失敗します。

const pAll = Promise.all([p1, p2])
pAll.then(
  //注意,此次的value是个复数,也就是说最后输出的 values 是个数组,起里面值的顺序和all里面promise数组一致,和执行完成的先后顺序没有关系,不过用Promise.race时,和执行完成的先后顺序有关系
  values => {
    
    
    console.log('all onResolved()', values)
  },
  reason => {
    
    
    console.log('all onRejected()', reason)
  }
)
  1. Promise.raceメソッド: (約束) => {}
    promises: 配列が含まれますn説明promise:
    新しいものを返しますpromise。最初に完了したpromise結果の状態が最終的な結果の状態になります。
//根据race这个单词的意思可知,这个方法更强调的是谁先完成,我就先返回它的值
const pRace = Promise.race([p1, p2, p3])
pRace.then(
  value => {
    
    
    console.log('race onResolved()', value)
  },
  reason => {
    
    
    console.log('race onRejected()', reason)
  }
)

コールバック関数: ユーザーが定義します。自分で呼び出すわけではありませんが、最終的に実行されます。

いくつかの重要な問題を約束する

  1. プロミスの状態を変更するにはどうすればよいですか?
  • solve(value): 現在保留中の場合は解決されます。
  • 拒否(理由): 現在保留中の場合、拒否されます。
  • 例外をスローする: 現在保留中の場合は拒否されます。
const p = new Promise((resolve, reject) => {
    
    
  // resolve(1) // promise变为resolved成功状态
  // reject(2) // promise变为rejected失败状态
  // throw new Error('出错了') // 抛出异常, promse变为rejected失败状态, reason为 抛出的error
      throw 3 // 抛出异常, promse变为rejected失败状态, reason为 抛出的3
    })
    p.then(
      value => {
    
    },
      reason => {
    
    console.log('reason', reason)}
    )
    p.then(
      value => {
    
    },
      reason => {
    
    console.log('reason2', reason)}
    )
  1. 複数promiseの成功/失敗コールバック関数を指定すると、それらはすべて呼び出されますか?

答え: はい。ただし、promise対応する状態に遷移する場合には条件があります都会调用

  1. Promise の状態を変更してコールバック関数を最初に指定するのは誰ですか?

回答: どちらも可能です。通常はコールバックを指定してから状態を変更しますが、状態を変更してからコールバックを指定することも可能です。

  • 最初に状態を変更してからコールバックを指定するにはどうすればよいですか?

    ①executor内でresolve()/reject()を直接呼び出す

    ②then()を呼び出す前に、より長い時間遅延します。

    new Promise((resolve, reject) => {
          
          
      	resolve(1) //先改变的状态(同时指定数据)
    }).then(// 后指定回调函数, 异步执行回调函数
      	value => {
          
          console.log('value2', value)},
      	reason => {
          
          console.log('reason2', reason)}
    )
    //验证 .then 里面的回调函数是同步执行,还是异步执行,结果:异步执行
    //即,执行器函数里面的 resolve(1)和 .then 都是同步执行,而 .then 里面的 value和 reason 回调函数都是异步执行
    console.log('-------')
    

    要約:promiseはい、コールバック関数は成功でも失敗でも常に非同期で実行され、条件が満たされた場合、つまり状態が変化した場合でも、すぐに実行されるわけではありません。

  • 最初にコールバック関数を指定してから状態を変更するにはどうすればよいですか? 従来型

     // 常规: 先指定回调函数, 后改变的状态
    new Promise((resolve, reject) => {
          
          
        setTimeout(() => {
          
          
          resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数
        }, 1000);
    }).then(// 先指定回调函数, 保存当前指定的回调函数
        value => {
          
          },
        reason => {
          
          console.log('reason', reason)}
    )
    
  • データはいつ利用可能になりますか?

    ①最初にコールバックを指定すると、状態が変化したときにコールバック関数が呼び出されてデータを取得します。

    ②先に状態を変更した場合、コールバックを指定するとコールバック関数が呼び出されてデータを取得します。

  1. promise.then()返される新しい結果ステータスはpromise何によって決まりますか? (これが最も重要です)

(1) 単純な式:then() で指定したコールバック関数の実行結果により決定
(2) 詳細な式:
①例外がスローされた場合、新しい Promise は拒否され

スローされた例外が理由になります

 new Promise((resolve, reject) => {
    
    
      // resolve(1)
      reject(1)
    }).then(
      value => {
    
    
        console.log('onResolved1()', value)
        // return 2
        // return Promise.resolve(3)
        // return Promise.reject(4)
        throw 5
      },
      reason => {
    
    
        console.log('onRejected1()', reason)
        // return 2
        // return Promise.resolve(3)
        // return Promise.reject(4)
        throw 5
      }
    ).then(
      value => {
    
    
        console.log('onResolved2()', value)
      },
      reason => {
    
    
        console.log('onRejected2()', reason)
      }
)
  1. promise複数の操作タスクを直列に接続するにはどうすればよいですか? (同期タスクまたは非同期タスクの場合があります)

回答: (1)新しいタスクpromiseを返すことは、連鎖呼び出しと見なすことができます。(2)連鎖呼び出しを通じて複数の同期タスクまたは非同期タスクを連鎖させること。ただし、非同期の場合は、非同期操作をカプセル化するために使用されるため、ラップする必要があります。(詳細については、2 番目の内部非同期タスクを参照してください)then()promise,then()
thenpromisepromise.then

new Promise((resolve, reject) => {
    
    
      resolve(1)
    }).then(
      value => {
    
    
        console.log('onResolved1()', value)
        return 2 //同步操作
      },
    ).then(
      value => {
    
    
        console.log('onResolved12()', value)
        return new Promise((resolve,reject) =>{
    
    
          //注意:这是一个异步任务,所以必须用promise来封装
          setTimeout(() =>{
    
    
            resolve(3)
          },1000)
    	})
      },
    ).then(
      value => {
    
    
        console.log('onResolved3()', value)
      },
    )
})

注:promise複数の操作タスクを直列に接続する場合、promise.then()最初の操作タスクのコールバック関数の型は 2 番目の操作タスクのpromise.then()コールバック関数には影響しません。2 番目の操作タスクのコールバック関数にのみ影響しますが、最初の操作タスクのコールバック関数の戻り値promise.then()のみに影響しますpromise.then()

例えば:

new Promise((resolve, reject) =>{
    
    
  resolve(1)
}).then(
  reason =>{
    
    
    return 2
  }
).then(
	value =>{
    
    
    console.log(value)
  },
  reason =>{
    
    
    console.log(reason)
  }
)

上記のコードに注目してください。最初のコードでは.then()、失敗したコールバック関数が実行されますが、その戻り値は( 、または)onrejectedではありません。つまり、失敗したコールバックは実行されますが、成功したコールバックは次のコードで実行されます异常throwreturn Promise.resolve().then

  1. promise例外の送信/侵入?

(1)promiseチェーンthenコールを使用する場合、最後に失敗したコールバックを指定できます。
(2) 前の操作での例外はすべて、最後に失敗したコールバックに渡されて処理されます。

  1. 壊れたpromiseチェーン?

(1) チェーンコールを使用するとpromise途中thenで中断され、後続のコールバック関数は呼び出されません(2) メソッド:
コールバック関数でpendding状態オブジェクトを返すpromise

return new Promise(() => {
    
    }) // 返回一个pending的promise  中断promise链

補足:アロー関数: には=>関数がありますが、ないことreturnが前提です。=>{}

おすすめ

転載: blog.csdn.net/qq_41769706/article/details/107522852