簡易版のPromiseを実現します.
11909 ワード
前言
PromiseはJavaScriptの中で非同期の操作に非常に重要な構造関数ですが、どうやって実現されますか?
以下はオリジナルJavaScriptで簡易版のPromiseを実現し、以下のコードを実現します.
Promiseを使ったことがある友達はすべて知っていて、Promiseは関数fnを受け取ってそしてそれを呼び出して、Promiseはまた状態(pending、reolved、reject)の属性値statusを表すべきで、1つのvalueストアthen回調の時に伝える値、もう一つのthen方法があります.他の方法はしばらく考えません.
連鎖式then
以下のコードを実装する場合、第二のthenの実行関数は、第一のthenの戻り値のブール値に基づいて決定される.
これで簡単版のPromiseが実現しました.もちろん細かいところまでは考えられませんでしたが、実現地は非常に粗いです.
PromiseはJavaScriptの中で非同期の操作に非常に重要な構造関数ですが、どうやって実現されますか?
以下はオリジナルJavaScriptで簡易版のPromiseを実現し、以下のコードを実現します.
function Promise(???){
???
return ???
}
var promise = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve('hello');
}, 3000);
});
promise.then(
val => {
console.log(' ', val);// hello
},
val => {
console.log(' ', val);
}
);
実現するPromiseを使ったことがある友達はすべて知っていて、Promiseは関数fnを受け取ってそしてそれを呼び出して、Promiseはまた状態(pending、reolved、reject)の属性値statusを表すべきで、1つのvalueストアthen回調の時に伝える値、もう一つのthen方法があります.他の方法はしばらく考えません.
function Promise(fn) {
// status peding
let status = 'pending';
// then
let value;
// then
let onResolvedCallback;
let onRejectedCallback;
// fn resolve
function resolve(data) {
// status fulfilled
status = 'fulfilled';
//
value = data;
toDoThen(onResolvedCallback, onRejectedCallback);
}
// fn reject
function reject(data) {
// status rejected
status = 'rejected';
//
value = data;
toDoThen(onResolvedCallback, onRejectedCallback);
}
// resolve reject
function toDoThen(onFulfill, onReject) {
// fulfilled , then
if (status === 'fulfilled') {
onFulfill && onFulfill(value);
status = 'pending';
// rejected , then
} else if (status === 'rejected') {
onReject && onReject(value);
status = 'pending';
// peding, resolve reject , then , resolve reject
} else {
onResolvedCallback = onFulfill;
onRejectedCallback = onReject;
}
}
// then toDoThen
this.then = function(onFulfill, onReject) {
toDoThen(onFulfill, onReject);
};
// fn
fn(resolve, reject);
return this;
}
テストvar promise = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve('hello');
}, 3000);
});
promise.then(
val => {
console.log(' ', val);
},
val => {
console.log(' ', val);
}
);
実行時には「初めての成功」と「ハロー」が印刷されます.連鎖式then
以下のコードを実装する場合、第二のthenの実行関数は、第一のthenの戻り値のブール値に基づいて決定される.
promise
.then(
val => {
console.log(' ', val);
return 'world';
},
val => {
console.log(' ', val);
return false;
}
)
.then(
val => {
console.log(' ', val);
},
val => {
console.log(' ', val);
}
);
ここでチェーンthenを実現するには、thenが戻ってくるのもPromiseオブジェクトでなければならず、最初のthenの戻り値から次のthenがどの関数を呼び出すかを決定する.function Promise(fn) {
// status peding
let status = 'pending';
// then
let value;
// then
let onResolvedCallback;
let onRejectedCallback;
// fn resolve
function resolve(data) {
// status fulfilled
status = 'fulfilled';
//
value = data;
toDoThen(onResolvedCallback, onRejectedCallback);
}
// fn reject
function reject(data) {
// status rejected
status = 'rejected';
//
value = data;
toDoThen(onResolvedCallback, onRejectedCallback);
}
// resolve reject
function toDoThen(onFulfill, onReject) {
// fulfilled , then
if (status === 'fulfilled') {
onFulfill && onFulfill(value);
status = 'pending';
// rejected , then
} else if (status === 'rejected') {
onReject && onReject(value);
status = 'pending';
// peding, resolve reject , then , resolve reject
} else {
onResolvedCallback = onFulfill;
onRejectedCallback = onReject;
}
}
this.then = function(onFulfill, onReject) {
return new Promise((resolve, reject) => {
toDoThen(
val => {
let result = onFulfill(val);
// then then
result ? resolve(result) : reject(result);
},
err => {
let result = onReject(err);
// then then
result ? resolve(result) : reject(result);
}
);
});
};
// fn
fn(resolve, reject);
return this;
}
実行してみますvar promise = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve('hello');
}, 3000);
});
promise
.then(
val => {
console.log(' ', val);
return 'world';
},
val => {
console.log(' ', val);
return false;
}
)
.then(
val => {
console.log(' ', val);
},
val => {
console.log(' ', val);
}
)
プログラムは「初めての成功」と「二回目の成功」を順次出力します.これで簡単版のPromiseが実現しました.もちろん細かいところまでは考えられませんでしたが、実現地は非常に粗いです.