約束
-
- 1. 意味
- 2番目に、Promiseの使用
-
- 1. Promise コンストラクター: Promise(executor) {}
- 2. Promise.prototype.then 方法: `(onResolved, onRejected) => {}`
- 3. Promise.resolve メソッド: `Promise.resolve(value) => {}`
- 4. Promise.reject 方法: `Promise.resolve(reason) => {}`
- 5. Promise.all 方法: `Promise.all(iterable) => {}`
- 7. Promise.race方法:Promise.race(iterable) => {}
- 3. いくつかの重要な約束事項
1. 意味
約束は非同期プログラミングの解決策
1.コンセプト
簡単に言うと、将来終了するイベント (通常は非同期操作) の結果を保持するコンテナーです。構文的には、Promise
非同期操作のメッセージを取得できるオブジェクト。Promise
統合された を提供しAPI
、あらゆる種類の非同期操作を同じ方法で処理できます。
非同期プログラミング: fs ファイル操作、データベース操作、Ajax、タイマー;
2. 特長
-
オブジェクトの状態は外界の影響を受けません。Promise オブジェクトは 3 つの状態を持つ非同期操作を表します
- 保留中: 進行中
- 満たされました: 成功しました
- 拒否されました: 失敗しました
非同期操作の結果のみが現在の状態を決定でき、他の操作はこの状態を変更できません。
-
一度状態が変化すると再度変化することはなく、いつでもこの結果が得られます。状態変化には、
pending
への変化fulfilled
と へのpending
変化の2 つの状態しかありませんrejected
。
3. 基本的な使い方
ES6 では、Promise
オブジェクトはPromise
インスタンスを生成するために使用されるコンストラクターであると規定されています。
// Promise构造函数接受一个函数(执行器函数)作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
// 在异步操作成功时调用,并将异步操作的结果,作为参数value传递出去;
resolve(value);
} else {
// 在异步操作失败时调用,并将异步操作报出的错误,作为参数error/reason传递出去。
reject(error);
}
});
Promise インスタンスが生成された後、 then メソッドを使用して、解決された状態と拒否された状態のコールバック関数をそれぞれ指定できます。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then
メソッドは 2 つのコールバック関数をパラメータとして受け入れることができます。
- 最初のコールバック関数は、
Promise
オブジェクトの状態が変化したresolved
ときに呼び出されます。 - 2 番目のコールバック関数は、
Promise
オブジェクトの状態が変化したときに呼び出されますrejected
。
どちらの関数もオプションであり、必ず指定する必要はありません。これらはすべて、Promise
オブジェクトから渡された値をパラメータとして受け入れます。
// 创建一个新的p对象promise
const p = new Promise((resolve, reject) => {
// 执行器函数
// 执行异步操作任务
setTimeout(() => {
const time = Date.now()
// 如果当前时间是偶数代表成功,否则失败
if (time % 2 == 0) {
// 如果成功,调用resolve(value)
resolve('成功的数据,time=' + time)
} else {
// 如果失败,调用reject(reason)
reject('失败的数据,time=' + time)
}
}, 1000);
})
p.then(
value => {
// 接收得到成功的value数据 onResolved
console.log('成功的回调', value) // 成功的回调 成功的数据,time=1615015043258
},
reason => {
// 接收得到失败的reason数据 onRejected
console.log('失败的回调', reason) // 失败的回调 失败的数据,time=1615014995315
}
)
4. Promise を使用する理由
1. コールバック関数の指定方法がより柔軟になりました
旧: 非同期タスクを開始する前に指定する必要があります
// 1. 纯回调的形式
// 成功的回调函数
function successCallback(result) {
console.log("声音文件创建成功:" + result);
}
// 失败的回调函数
function failureCallback(error) {
console.log("声音文件创建失败:" + error);
}
// 必须先指定回调函数,再执行异步任务
createAudioFileAsync(audioSettings, successCallback, failureCallback) // 回调函数在执行异步任务(函数)前就要指定
Promise: 非同期タスクを開始する => Promise オブジェクトを返す => コールバック関数を Promise オブジェクトにバインドする (非同期タスクの終了後に指定することも可能)
// 2. 使用Promise
const promise = createAudioFileAsync(audioSettings); // 执行2秒
setTimeout(() => {
promise.then(successCallback, failureCallback) // 也可以获取
}, 3000);
2. コールバック地獄の問題を解決できるチェーンコールをサポートします。
コールバック 地獄: コールバック関数はネストされており、外側のコールバック関数の非同期実行の結果が、内側のネストされたコールバック関数の実行条件となります。
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result:' + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
promise
連鎖呼び出しによるコールバック地獄の解決
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log('Got the final result:' + finalResult)})
.catch(failureCallback)
Promise を使用した Ajax の実装
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
上記のコードでは、getJSON は XMLHttpRequest オブジェクトのカプセル化であり、JSON データの HTTP リクエストを発行し、Promise オブジェクトを返すために使用されます。getJSON 内では、resolve 関数と拒否関数の両方がパラメーターを使用して呼び出されることに注意してください。
2番目に、Promiseの使用
1. Promise コンストラクター: Promise(executor) {}
- エグゼキューター関数:同期実行(解決、拒否) => {}
- solve 関数: 内部定義が成功したときに呼び出される関数solve(value)
- 拒否関数: 内部定義が失敗したときに呼び出される関数拒否(reason)
説明: エグゼキュータはエグゼキュータであり、Promise 内で同期的に直ちにコールバックされ、非同期操作の解決/拒否がエグゼキュータで実行されます。
2. Promise.prototype.then 方法: (onResolved, onRejected) => {}
指定两个回调(成功+失败)
(1)onResolved
関数: 成功コールバック関数(value) => {}
(2)onRejected
関数:失敗時コールバック関数(reason) => {}
説明:value
成功の場合は成功コールバック、reason
失敗の場合は失敗コールバックを指定し、新しいpromise
オブジェクトを返します。
2、Promise.prototype.catch 方法: p.(onRejected) => {}
失敗時のコールバックを指定する
(1) onRejected 関数: 失敗したコールバック関数 (理由) => {}
説明: これはthen()
糖衣構文であり、以下と同等です。then(undefined, onRejected)
new Promise((resolve, reject) => {
// excutor执行器函数
setTimeout(() => {
if(...) {
resolve('成功的数据') // resolve()函数
} else {
reject('失败的数据') //reject()函数
}
}, 1000)
}).then(
value => {
// onResolved()函数
console.log(value) // 成功的数据
}).catch(
reason => {
// onRejected()函数
console.log(reason) // 失败的数据
}
)
3. Promise.resolve 方法: Promise.resolve(value) => {}
成功/失敗promise
オブジェクトを返します。
value
: 成功データまたはpromise
オブジェクト
1. 受信パラメータが非 Promise タイプのオブジェクトである場合、返される結果は成功した Promise オブジェクトです
let p1 = Promise.resolve(521);
console.log(p1); // Promise {<fulfilled>: 521}
2. 受信パラメータがPromise
オブジェクトの場合、パラメータの結果によって次resolve
の結果が決まります。
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('OK'); // 成功的Promise
reject('Error');
}));
console.log(p2);
p2.catch(reason => {
console.log(reason);
})
4. Promise.reject 方法: Promise.resolve(reason) => {}
(1) reason
: 失敗の理由
説明: 失敗したpromise
オブジェクトを返します。
let p = Promise.reject(521);
let p2 = Promise.reject('iloveyou');
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('OK');
}));
console.log(p);
console.log(p2);
console.log(p3);
Promise.resolve()
/Promise.reject()
メソッドは、Promise オブジェクトをすばやく取得するための糖衣構文です。
5. Promise.all 方法: Promise.all(iterable) => {}
iterable
: n を含むpromise
反復可能なオブジェクト( またはArray
など)String
promise
すべてが成功した場合にのみpromise
成功し、1 つが失敗した場合は直接失敗する新しいものを返します。
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.reject('Error');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
const pAll = Promise.all([p1, p2, p3])
const pAll2 = Promise.all([p1, p2])
//因为其中p3是失败所以pAll失败
pAll.then(
value => {
console.log('all onResolved()', value)
},
reason => {
console.log('all onRejected()', reason)
}
)
// all onRejected() 3
pAll2.then(
values => {
console.log('all onResolved()', values)
},
reason => {
console.log('all onRejected()', reason)
}
)
// all onResolved() [1, 2]
7. Promise.race方法:Promise.race(iterable) => {}
iterable
: n を含むpromise
反復可能なオブジェクト( またはArray
など)String
- 新しい
promise
、最初に完了したpromise
結果状態、つまり最終結果状態を返します。
const pRace = Promise.race([p1, p2, p3])
// 谁先完成就输出谁(不管是成功还是失败)
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
pRace.then(
value => {
console.log('race onResolved()', value)
},
reason => {
console.log('race onRejected()', reason)
}
)
//race onResolved() 2
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//调用
const result = Promise.race([p1, p2, p3]);
console.log(result);
3. いくつかの重要な約束事項
1. プロミスの状態を変更するにはどうすればよいですか?
(1) resolve(value)
: 現在の場合は次pending
のようになりますresolved
(2) reject(reason)
: 現在の場合はpending
`rejected` になります
(3) 例外をスローする: 現在の場合、次 pending
のようになります。rejected
const p = new Promise((resolve, reject) => {
//resolve(1) // promise变为resolved成功状态
//reject(2) // promise变为rejected失败状态
throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
})
p.then(
value => {
},
reason => {
console.log('reason',reason)}
)
// reason Error:出错了
2. Promise で複数の成功/失敗コールバック関数が指定されていますが、それらはすべて呼び出されますか?
Promise が対応する状態に変化したときに呼び出されます
const p = new Promise((resolve, reject) => {
//resolve(1)
reject(2)
})
p.then(
value => {
},
reason => {
console.log('reason',reason)}
)
p.then(
value => {
},
reason => {
console.log('reason2',reason)}
)
// reason 2
// reason2 2
3. Promise の状態を変更し、コールバック関数を指定するのはどれが最初でしょうか?
(1) どちらも可能 通常はコールバックを指定して状態を変更しますが、状態を変更してからコールバックを指定することも可能です
(2) 最初に状態を変更してからコールバックを指定するにはどうすればよいですか?
①executor内でresolve()/reject()を直接呼び出す
② then()を呼び出すまでの時間を長くする
let p = new Promise((resolve, reject) => {
// setTimeout(() => {
resolve('OK');
// }, 1000); // 有异步就先指定回调,否则先改变状态
});
p.then(value => {
console.log(value);
},reason=>{
})
(3) データはいつ入手可能になりますか?
①最初にコールバックを指定すると、状態が変化したときにコールバック関数が呼び出されてデータを取得します。
②先に状態を変更した場合、コールバックを指定するとコールバック関数が呼び出されてデータを取得します。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1) // 改变状态
}, 1000)
}).then( // 指定回调函数 (先指定)
value => {
},
reason =>{
}
)
この時点で、最初にコールバック関数を指定し、現在指定されているコールバック関数を保存し、次に状態を変更し (データを指定しながら)、以前に保存したコールバック関数を非同期に実行します。
new Promise((resolve, reject) => {
resolve(1) // 改变状态
}).then( // 指定回调函数
value => {
},
reason =>{
}
)
この書き方は、まず状態を変更(同時にデータを指定)し、次にコールバック関数を指定(再度保存する必要はありません)し、コールバック関数を非同期で直接実行します。
4.promise.then() によって返される新しい Promise の結果の状態は何によって決まりますか?
(1) 単純な式:then()で指定したコールバック関数の実行結果により決定
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
console.log(result);
(2) 詳細表現:
① 例外がスローされた場合、新しい Promise は拒否されます。理由はスローされた例外です。
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//1. 抛出错误
throw '出了问题';
}, reason => {
console.warn(reason);
});
console.log(result);
② Promise 以外の値が返された場合、新しい Promise は解決され、value は戻り値になります。
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//2. 返回结果是非 Promise 类型的对象
return 521;
}, reason => {
console.warn(reason);
});
console.log(result);
③ 別の新しいPromiseが返された場合、このPromiseの結果は新しいPromiseの結果になります
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//3. 返回结果是 Promise 对象
return new Promise((resolve, reject) => {
// resolve('success');
reject('error');
});
}, reason => {
console.warn(reason);
});
console.log(result);
new Promise((resolve, reject) => {
resolve(1)
}).then(
value => {
console.log('onResolved1()', value)
},
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved2()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onResolved1() 1
// onResolved2() undefined
new Promise((resolve, reject) => {
resolve(1)
}).then(
value => {
console.log('onResolved1()', value)
//return 2 // onResolved2() 2
//return Promise.resolve(3) // onResolved2() 3
//return Promise.reject(4) // onRejected2() 4
//throw 5 // onRejected2() 5
},
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved2()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onResolved1() 1
// onResolved2() undefined
// Promise {<fulfilled>: undefined}
// 对应输出如上所示
5. Promise は複数の操作タスクをどのように連鎖させますか?
(1)開くことができる新しいチェーン コールpromise
を返します。then()
promise
then()
(2)then
複数の同期・非同期タスクをチェーンコールで直列に接続
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve("success");
});
}).then(value => {
console.log(value); // success
}).then(value => {
console.log(value); // undefined
})
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行任务1(异步)')
resolve(1)
}, 1000)
}).then(
value => {
console.log('任务1的结果', value)
console.log('执行任务2(同步)')
return 2 // 同步任务直接return返回结果
}
).then(
value => {
console.log('任务2的结果', value)
return new Promise((resolve, reject) => {
// 异步任务需要包裹在Promise对象中
setTimeout(() => {
console.log('执行任务3(异步)')
resolve(3)
}, 1000)
})
}
).then(
value => {
console.log('任务3的结果', value)
}
)
// 执行任务1(异步)
// 任务1的结果 1
// 执行任务2(同步)
// 任务2的结果 2
// 执行任务3(异步)
// 任务3的结果 3
6. 約束の連鎖を断ち切る?
(1) のチェーンコールを使用すると途中promise
で then
中断され、後続のコールバック関数が呼び出されなくなります
(2) 方法:コールバック関数でpendding
状態promise
オブジェクトを返す
new Promise((resolve, reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
}
).then(
value => {
console.log('onResolved2()', value)
return 3
}
).then(
value => {
console.log('onResolved3()', value)
}
).catch(
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved4()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onRejected1() 1
// onResolved4() undefined