promise
それは何ですか
抽象的な観点から見ると、これは新しいソリューションです。JS
は、Solve での非同期プログラミングのソリューションです。古い解決策は、純粋なコールバックです (ただし、promise
コールバック関数も含まれているため、コールバック関数を追加しました纯
)。そのため、コールバック地獄があります。
文法的に言えば、Promise
これはコンストラクターです。したがって、インスタンス オブジェクトを作成し、そのインスタンス オブジェクトに処理を指示することができます。逆に、一般的な関数であれば、関数自体が何かを行うことになります。
機能の観点:promise
オブジェクトは非同期操作をカプセル化するために使用され、その結果を取得できます。
promise
ステータスは次のように変化します。
pending
になるresolved
pending
になるrejected
- この2州のみ
pending
初期化状態を示します- オブジェクト
promise
は 1 回だけ変更できます - 成功しても失敗しても結果データはある
- 成功した結果データを一般的に と呼び
vlaue
、失敗した結果データを一般的に と呼びます。reason
promise
基本的なプロセスは次のとおりです。
説明:
- 新しいオブジェクトを作成し、
promise
新しく作成されたオブジェクトpromise
の状態がpeding
状態、つまり初期化状態になります。 - コンストラクターに
promise
パラメータ (parameter ) を渡し执行器函数
、执行器函数
非同期タスクを実行します。 - 非同期タスクの実行は、最終的には成功する場合も失敗する場合もあります。成功した場合は
resolve()
メソッドが実行され、promise
オブジェクトの状態がresolved
状態になり、失敗した場合はreject()
メソッドが実行され、promise
オブジェクトの状態がrejected
状態になります。 - 状態が変化したら、成功または失敗のコールバック関数を呼び出します。
- 成功または失敗のコールバック関数が渡される
.then
か.catch
指定されます。このうち、.then
成功したコールバックと失敗したコールバックの両方を指定できますが、.catch
失敗したコールバックのみを指定できます。 - 最後に、新しいオブジェクト
.then
が返されますpromise
Promise の基本的な使い方:
なぜ約束するのか
純粋なコールバック: 実際に非同期タスクを実行するときは、コールバック関数を指定する必要があります。つまり、最初にコールバック関数を指定してから非同期タスクを開始する必要があり、次のようになる必要があります之前
。事先
promise
オブジェクト: 非同期タスクの開始後にコールバック関数を指定できますが、非同期タスクが成功するか結果が得られる前にコールバック関数を指定することもできます。もちろん、非同期タスクの結果が得られた後でもコールバック関数を指定できます。これも純粋なコールバックでは実行できないことです。つまり、純粋なコールバック関数と比較して、promise
オブジェクトはコールバック関数を指定する方法がより柔軟です。
概要:promise
コールバック関数を指定する方法がより柔軟になりました。通常、コールバック関数は非同期タスクの実行後に指定します。
纯回调
: 非同期タスクを開始する前に指定する必要があります
Promise
コンストラクター自体は実行関数を受け取りexcutor
、実行関数はexcutor
2 つの関数 (1 つはresolve
関数、もう 1 つはreject
関数) を受け取ります。また、executor 関数はexcutor
同期コールバック関数であり、実際の非同期コードはexecutor 関数内に記述されますexcutor
。
Promise
のプロトタイプ オブジェクトにはthen
2 つのパラメータを指定するメソッドが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
-
Promise
コンストラクター: Promise (エクスキューター) {}
excutor
エグゼキューター関数: 同期実行 (解決、拒否) => {}
resolve
関数: 内部定義が成功したときに呼び出す関数 value => {} 関数
reject
: 内部定義が失敗したときに呼び出す関数reason => {}
注:同期コールバックは内部で実行excutor
されPromise
、非同期操作はエグゼキューターで実行されます。 -
Promise.prototype.then
メソッド: (onResolved, onRejected) => {}
onResolved
関数: 成功コールバック関数 (値) => {}
onRejected
関数: 失敗コールバック関数 (理由) => {}
説明: 成功値を取得するための成功コールバックと失敗理由を取得するための失敗コールバックを指定し、新しい Promise オブジェクトを返します。これはチェーン呼び出しをサポートするための前提条件でもありますpormise
。 -
Promise.prototype.catch
メソッド: (onRejected) => {}
onRejected
関数: 失敗したコールバック関数 (理由) => {}
説明:then()
糖衣構文、以下と同等:then(undefined, onRejected)
-
Promise.resolve
メソッド: (値) => {}
値: 成功したデータまたはpromise
オブジェクト説明:本質的に糖衣構文である
成功/失敗オブジェクトを返します。promise
//二者都返回一个promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 100);
})
const p2 = Promise.resolve(2)
Promise.reject
メソッド: (reason) => {}
reason
: 失敗の理由
説明: 失敗した Promise オブジェクトを返します。これは本質的には糖衣構文です。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(1)
}, 100);
})
const p3 = Promise.reject(3)
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)
}
)
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)
}
)
コールバック関数: ユーザーが定義します。自分で呼び出すわけではありませんが、最終的に実行されます。
いくつかの重要な問題を約束する
- プロミスの状態を変更するにはどうすればよいですか?
- 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)}
)
- 複数
promise
の成功/失敗コールバック関数を指定すると、それらはすべて呼び出されますか?
答え: はい。ただし、promise
対応する状態に遷移する場合には条件があります都会调用
。
- 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)} )
-
データはいつ利用可能になりますか?
①最初にコールバックを指定すると、状態が変化したときにコールバック関数が呼び出されてデータを取得します。
②先に状態を変更した場合、コールバックを指定するとコールバック関数が呼び出されてデータを取得します。
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)
}
)
promise
複数の操作タスクを直列に接続するにはどうすればよいですか? (同期タスクまたは非同期タスクの場合があります)
回答: (1)新しいタスクpromise
を返すことは、連鎖呼び出しと見なすことができます。(2)連鎖呼び出しを通じて複数の同期タスクまたは非同期タスクを連鎖させること。ただし、非同期の場合は、非同期操作をカプセル化するために使用されるため、ラップする必要があります。(詳細については、2 番目の内部非同期タスクを参照してください)then()
promise,
then()
then
promise
promise
.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
ではありません。つまり、失敗したコールバックは実行されますが、成功したコールバックは次のコードで実行されます。异常
throw
return Promise.resolve()
.then
promise
例外の送信/侵入?
(1)promise
チェーンthen
コールを使用する場合、最後に失敗したコールバックを指定できます。
(2) 前の操作での例外はすべて、最後に失敗したコールバックに渡されて処理されます。
- 壊れた
promise
チェーン?
(1) チェーンコールを使用するとpromise
途中then
で中断され、後続のコールバック関数は呼び出されません(2) メソッド:
コールバック関数でpendding
状態オブジェクトを返すpromise
return new Promise(() => {
}) // 返回一个pending的promise 中断promise链
補足:アロー関数: には=>
関数がありますが、ないことreturn
が前提です。=>
{}