有不對的,可以指出來,我這裏只是想記一下筆記,方便我以後看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
let st = setTimeout;
const FULL_FILLED = 'fullFilled'; // 成功
const REJECTED = 'rejected'; // 失敗
const PENDING = 'pending';//這裏用的setTimeout做異步操作,所以在執行異步之前的時間裏,狀態都是pending
let count = 0;
let Promise = function (fn) {//fn就是promise中的函數參數,這個參數有兩個內部定義好的resolve和reject函數參數
this.id = count++;
this.status = PENDING;
this.successCallbacks = [];//用來保存then裏邊的成功回調函數
this.failedCallbacks = [];//用來保存then裏邊失敗的回調函數
let resolve = (v)=> {//promise的resolve執行,後會執行then中的成功回調函數,這個v參數,會傳過去
setTimeout(()=>{
// resolve(value);
this.value = v;
this.status = FULL_FILLED;//如果成功會從pending狀態變成fullFilled
this.successCallbacks.forEach( fn => fn(this.value) )
})
}
let reject = (v) => {
setTimeout(()=>{
// reject(value);
this.value = v;
this.status = REJECTED;//失敗的話從pending狀態變成rejected狀態
this.failedCallbacks.forEach( fn => fn(this.value) )
})
}
try {
fn(resolve,reject)
} catch (e) {
reject(e); // new Promise().then 執行失敗
}
}
function excutePromise (promiseOrVal,resolve,reject) {//這是第一個參數,是判斷then中的返回是一個【promise】還是【普通的基本類型值】
if (promiseOrVal instanceof Promise) {
// 還沒有寫 (then 從promise中取值)
promiseOrVal.then((v)=>{
excutePromise(v,resolve,reject);//這個就是一直遞歸判斷then中返回的是不是promise還是基本值的函數
});
} else {
// value 基本數據類型
resolve(promiseOrVal); // then中如果返回的是【基本類型的值】執行resolve函數,就直接進行到下一個的.then的回調函數裏面,否則的話就是promise,繼續進行循環遞歸去判斷返回的是promise還是基本類型值
}
}
// then 一定是要返回Promise供外部.then
Promise.prototype.then = function (onFullFilledFn,onRejectedFn) {
let chainPromise;//這個結果就是then的返回值,一定要是promise,供外部的.then
// 如果當前,3秒以內,狀態是【Pending】
if (this.status === PENDING) {//如果是pending狀態,就說明,也不知道要走成功還是失敗,所以有兩種可能
chainPromise = new Promise((resolve,reject)=>{
// 是pending狀態,先把成功或者是失敗的回調函數保存起來,等待狀態改變後,直接調用,這個目的就是保存函數
this.successCallbacks.push(()=>{
try {
setTimeout(()=>{
// resovle後纔會被髮布,所執行
let value = onFullFilledFn(this.value);
// value有可能是Promise, 也有可能是一般的值
excutePromise(value,resolve,reject);//這個函數就是去判斷返回的值是否是promise還是基本值,基本值的話,就會執行resolve,想定與放行開關,進入到下一個then中
})
}catch(e) {
reject(e);
}
});
this.failedCallbacks.push(()=>{
try {
setTimeout(()=>{
// reject後纔會被髮布,所執行
let value = onRejectedFn(this.value);
// value有可能是Promise, 也有可能是一般的值
excutePromise(value,resolve,reject);
})
}catch(e) {
reject(e);
}
})
});
}
if (this.status === FULL_FILLED) {//如果狀態是成功,直接走成功回調
chainPromise = new Promise((resolve,reject) => {
try {
setTimeout(()=>{
let value = onFullFilledFn(this.value);
excutePromise(value,resolve,reject);
})
} catch (e) {
reject(e);
}
});
}
if (this.status === REJECTED) {//如果狀態是失敗
chainPromise = new Promise((resolve,reject) => {
try {
let value = onRejectedFn(this.value);
excutePromise(value,resolve,reject);
} catch (e) {
reject(e);
}
});
}
return chainPromise;
}
// 模擬3組異步
// 返回的是Promise實例
new Promise(function (resolve,reject) {
console.log('promise執行了');//1
st(()=>{
console.log('第1件事。。。');//2
resolve('abcd');
},3000);
})
.then( (data)=> {
return new Promise((resovle,reject)=>{
st(()=>{
console.log('第2件事');//3
resovle('xxx');//這個執行了,纔會執行下一個then,它就是一個開關作用,這個參數會作爲下一個then的實參,
},3000);
});
})
.then((d)=>{
console.log('結束了',d);//4,d的值:【d:'xxx'】
})
</script>
</body>
</html>
.then一定是一個promise,供外部(後續)的.then才能執行,
.then 是立刻執行的,沒辦法控制它停止,每個then裏的回調函數,有可能是一個promise
或者一個普通的基本類型的值,如果是promise,只有resolve,纔會執行下一個then裏的
回調函數,否則直接往下執行;(有一個遞歸就是判斷then裏的回調函數是不是一個promise,如果是
就繼續遞歸)