Promiseとその使用
34617 ワード
Promiseとその使用
なぜPromiseが必要なのか
Promiseの提案は非同期シーンという分野の問題を解決するためである.この章ではまず現在のJSが非同期を処理する際にどのような問題があるかを説明し,その後Promiseがこれらの問題を処理する方案を与える.
なぜ非同期が必要なのか単一スレッド+イベント駆動(ブラウザJS,NodeJs,Redis,Nginx...) 従来の非同期処理スキームコールバック方式callback マルチスレッド(JS以外) CallBackスキームの問題点コールバックピラミッド フォーマット定義不統一(スタイル) 非同期構文(スタイル) 制御権(制御反転)-トリガ回数?トリガタイミング?トリガ周波数?
callbackの呼び出し関数(wait 1000)とcallbackを実現する関数(f 1)は一緒ではなく、callbackの実行は実装者(f 1)ではなく呼び出し元(wait 1000)に依存し、言い換えれば、私は関数を作成したが、この関数がどのように、いつ呼び出され、何回呼び出されるかは決定できない.これにより、コードの状態が信頼できなくなります.
例:
cb引き落とし業務への転送
オーダーの作成-開発グループ1
引き落とし-開発グループ2
引き落とし成功-開発グループ2
cbを呼び出して在庫を減らす--開発グループ1
引き落としに失敗しました--開発チーム2
開発グループ1が受注の作成と在庫の削減を担当すると仮定し、開発グループ2は控除業務を担当し、控除業務は非同期であり、コールバック関数cbに転送して控除結果を与える必要がある.ビジネスプロセスは、開発グループ1が受注を作成した後に在庫を1つ減らす動作を開発グループ2にコールバックとして渡すための引き落としモジュールである.通常はすべて正常ですが、開発グループ2で実装されたコードが間違っている場合、以下の可能性があります.コールバックcb正常実行1回 コールバックcb実行(0回) なしコールバックcbはN回N>1 を実行する.
開発グループ1としては、後の2つのシーンを処理する必要があるが、このロジックを組織するのは煩雑である.(変数記録+タイマ).煩雑な原因は、2つの異なる非同期プロセスを調整することであり、callbackモードでは2つ以上のcallbackをどのように調整するかの一般的なスキームが与えられていない.
Promiseの定義
英語のpromiseの意味は承諾で、1つは未来(非同期)で現金化した結果です.承諾には2つの状態があります:進行中、承諾を終了する結果には2つの可能性があります:成功して現金化して、約束を失います
正常終了fullfill
異常発生reject
pending
resolved
rejected
Promiseの2つの状態:pending,settled settledの2つの結果:resolved,rejected
Promiseは常に1つの結果があり、結果は変更できず、結果は何度も発生できない.
MDN Promise
定義#テイギ#
≪ステータス|Status|emdw≫
Promiseオブジェクト
正常に進行する
異常が発生する
作成
resolved
rejected
Promiseの簡単な使用チェーンコール(then/catchはPromiseを返します)
正常に進行する
異常が発生する
正常に進行する
異常が発生する
作成
作成
rejected
resolved
rejected
各種Promise方式のAPI
fetch node-fetch fs.promises
複数のPromiseを組織
複数の非同期オペレーションシリアルを編成するには、次の手順に従います.
並列:
へんしゅ制御時間の長い非同期操作promise+settimeout
一般的な関数としてパッケージ:inTime(p,timeOutSecond)
Promiseベースの他の非同期シーン処理
await同期形式の非同期呼び出しは、書く形式が思考に合っている.
リファレンスライブラリ
bluebird Q polyfill
なぜPromiseが必要なのか
Promiseの提案は非同期シーンという分野の問題を解決するためである.この章ではまず現在のJSが非同期を処理する際にどのような問題があるかを説明し,その後Promiseがこれらの問題を処理する方案を与える.
なぜ非同期が必要なのか
function wait1000(cb){
setTimeout(cb, 1000);
}
function wait1000(cb){
setInterval(cb, 1000);
}
function f1(){console.log('f1');}
wait1000(f1);
callbackの呼び出し関数(wait 1000)とcallbackを実現する関数(f 1)は一緒ではなく、callbackの実行は実装者(f 1)ではなく呼び出し元(wait 1000)に依存し、言い換えれば、私は関数を作成したが、この関数がどのように、いつ呼び出され、何回呼び出されるかは決定できない.これにより、コードの状態が信頼できなくなります.
例:
cb引き落とし業務への転送
オーダーの作成-開発グループ1
引き落とし-開発グループ2
引き落とし成功-開発グループ2
cbを呼び出して在庫を減らす--開発グループ1
引き落としに失敗しました--開発チーム2
開発グループ1が受注の作成と在庫の削減を担当すると仮定し、開発グループ2は控除業務を担当し、控除業務は非同期であり、コールバック関数cbに転送して控除結果を与える必要がある.ビジネスプロセスは、開発グループ1が受注を作成した後に在庫を1つ減らす動作を開発グループ2にコールバックとして渡すための引き落としモジュールである.通常はすべて正常ですが、開発グループ2で実装されたコードが間違っている場合、以下の可能性があります.
開発グループ1としては、後の2つのシーンを処理する必要があるが、このロジックを組織するのは煩雑である.(変数記録+タイマ).煩雑な原因は、2つの異なる非同期プロセスを調整することであり、callbackモードでは2つ以上のcallbackをどのように調整するかの一般的なスキームが与えられていない.
Promiseの定義
英語のpromiseの意味は承諾で、1つは未来(非同期)で現金化した結果です.承諾には2つの状態があります:進行中、承諾を終了する結果には2つの可能性があります:成功して現金化して、約束を失います
正常終了fullfill
異常発生reject
pending
resolved
rejected
Promiseの2つの状態:pending,settled settledの2つの結果:resolved,rejected
Promiseは常に1つの結果があり、結果は変更できず、結果は何度も発生できない.
MDN Promise
定義#テイギ#
function showContent(t){
console.log(' :', t);
}
function showError(err){
console.log(' :', err);
}
//Promise.prototype.constructor
var p = new Promise(function(resovle, reject){
fs.readFile('/tmp/l.log','utf8', function(err, data){
if(err){
reject(err);
}else{
resolve(data);
}
});
});
p.then(showContent, showError);
console.log(typeof p);
console.log(p);
console.log(p.)
≪ステータス|Status|emdw≫
Promiseオブジェクト
正常に進行する
異常が発生する
作成
resolved
rejected
Promiseの簡単な使用
p1.then(()=>p2).then(...)
正常に進行する
異常が発生する
正常に進行する
異常が発生する
作成
作成
rejected
resolved
rejected
//Promise.prototype.then(onFulfilled, onRejected)
//Promise.prototype.catch(onRejected)
//Promise.prototype.finally(onFinally) --- ES2018
p.then(f1, f2)
p.then(f1)
p.catch(f2)
p.then(f1).catch(f3)
p.catch(f2).finally(f4)
各種Promise方式のAPI
fetch node-fetch fs.promises
fetch('http://127.0.0.1:8080/api/get_user_list')
.then(x=>x.json())
.then(x=>console.log(x));
複数のPromiseを組織
複数の非同期オペレーションシリアルを編成するには、次の手順に従います.
p.then().then().then()...
並列:
//
Promise.all([p1, p2, p3, ...]),then()
//
Promise.race([p1, p2, p3, ...]).then()
//
function p(name){
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('Time: ', new Date(), name);
resolve(Date.now());
}, 1000);
})
}
let tasks = ['A','B','C','D','E','F'];
async function quee(){
while(tasks.length>0){
await p(tasks[0]);
tasks.unshift();
}
}
quee().then(()=>{
console.log('END, Time: ', new Date());
});
へんしゅ
function inTime1000(){
return new Promise(function(resolve, reject){
setTimeout(() => {
reject(null);
}, 1000);
})
}
Promise.race([
inTime1000(),
fetch('http://127.0.0.1:8080/api/get_user_list').then(x=>x.json())
]).then(data=>{
console.log(data);
}, err=>{
console.log(err);
});
一般的な関数としてパッケージ:inTime(p,timeOutSecond)
function inTime(p, timeOutSecond){
function inTimeTimer(second){
return new Promise(function(resolve, reject){
setTimeout(() => {
reject(null);
}, 1000*second);
})
}
return Promise.race([inTimeTimer(1.5), p]);
}
//inTime( fetch('http://127.0.0.1:8080/api/get_user_list').then(x=>x.json()), 1.2).then();
Promiseベースの他の非同期シーン処理
function p(name, cb){
setTimeout(() => {
console.log('Time: ', new Date(), name);
cb();
}, 1000);
}
let tasks = ['A','B','C','D','E','F'];
function next(){
if(tasks.length>0){
let t = tasks.shift();
p(t, function(){
console.log(' :', tasks);
next();
});
}else{
console.log('END, Time: ', new Date());
}
}
next();
setTimeout(()=>{
tasks.push('M');
},2100);
await同期形式の非同期呼び出しは、書く形式が思考に合っている.
function p(name){
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('Time: ', new Date(), name);
resolve(Date.now());
}, 1000);
})
}
let tasks = ['A','B','C','D','E','F'];
async function quee(){
while(tasks.length>0){
await p(tasks[0]);
tasks.shift();
console.log(' :', tasks);
}
}
quee().then(()=>{
console.log('END, Time: ', new Date());
});
setTimeout(()=>{
tasks.push('M');
},2100);
リファレンスライブラリ
bluebird Q polyfill