const demo = new Promise((resolve,reject)=>{
resolve('sajdhgas')
})
demo.then(a =>{console.log(a,'console')})
複製代碼
偷懶用的mdn的圖,見諒啊,各位大佬 (- . -)javascript
class PromiseDemo {
constructor(executor){
this.resolveResult = null;
this.rejectResult = null;
const resolve = (a) =>{
this.resolveResult = a;
}
const reject = (a) =>{
this.rejectResult = a;
}
try{
executor(resolve);
}catch(e){
reject(e)
}
}
then = (onResolve,onReject) =>{
if(onReject){
onReject(this.rejectResult)
}else{
onResolve(this.resolveResult)
}
return this
}
catch = onReject =>{
this.then(null,onReject)
}
}
const demo = new PromiseDemo((resolve,reject)=>{
//resolve('sajdhgas')
aaa
})
demo.then(a =>{console.log(a,'then')}).catch(a =>{console.log(a.message,'then')})
複製代碼
const PENDING = "pending";
const FULFILLED = "fullilled";
const REJECTED = "rejected";
class PromiseDemo {
constructor(executor) {
this.state = PENDING;
this.resolveResult = null;
this.rejectResult = null;
const resolve = a => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.resolveResult = a;
}
};
const reject = a => {
if (this.state === PENDING) {
this.state = REJECTED;
this.rejectResult = a;
}
};
try {
executor(resolve);
} catch (e) {
reject(e);
}
}
then = (onResolve, onReject) => {
if (onReject) {
onReject(this.rejectResult);
} else {
onResolve(this.resolveResult);
return this;
}
};
catch = onReject => {
this.then(null, onReject);
return this;
};
}
const demo = new PromiseDemo((resolve, reject) => {
resolve("sajdhgas");
resolve("sajdhgas1222");
});
demo
.then(a => {
console.log(a, "then");
})
.catch(a => {
console.log(a, "catch");
});
複製代碼
給promise內部加一個狀態鎖 statejava
對於異步: 在等待過程當中,把onResolve存起來,在resolve回調裏處理調用
對於同步: 在執行executor的時候把resolve的值存起來,在then裏直接調用es6
const PENDING = "pending";
const FULFILLED = "fullilled";
const REJECTED = "rejected";
class PromiseDemo {
constructor(executor) {
this.state = PENDING;
this.resolveResult = null;
this.rejectResult = null;
this.onReject = null;
this.onResolve = null;
const resolve = a => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.resolveResult = a;
this.onResolve(a);
}
};
const reject = a => {
if (this.state === PENDING) {
this.state = REJECTED;
this.rejectResult = a;
}
};
try {
executor(resolve);
} catch (e) {
reject(e);
}
}
then = (onResolve, onReject) => {
switch(this.state){
case PENDING:
this.onResolve = () => onResolve(this.resolveResult);
return this;
case FULFILLED:
onResolve(this.resolveResult);
return this;
case REJECTED:
this.onResolve = () => onResolve(this.resolveResult);
return this;
default:
break;
}
};
catch = onReject => {
this.then(null, onReject);
return this;
};
}
const demo = new PromiseDemo((resolve, reject) => {
setTimeout(() => {
resolve("sajdhgas");
}, 1000);
});
demo.then(a => {
console.log(a, "then");
});
複製代碼
then方法和catch方法 都返回一個新的 promise對象,Promise 對象的錯誤具備「冒泡」性質,會一直向後傳遞,直到被捕獲爲止。json
const PENDING = "pending";
const FULFILLED = "fullilled";
const REJECTED = "rejected";
class PromiseDemo {
constructor(executor) {
this.state = PENDING;
this.resolveResult = null;
this.rejectResult = null;
this.onReject = null;
this.onResolve = null;
const resolve = a => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.resolveResult = a;
this.onResolve();
}
};
const reject = a => {
if (this.state === PENDING) {
this.state = REJECTED;
this.rejectResult = a;
this.onReject();
}
};
try {
executor(resolve);
} catch (e) {
reject(e);
}
}
then = (onResolve, onReject) => {
const promise2 = new PromiseDemo((resolve, reject) => {
switch (this.state) {
case PENDING:
this.onResolve = () => {
// 這裏能夠打印到異步 promise的onResolve結果
// 獲取onResolve返回值 判斷返回值類型
const fulfilledResult = onResolve(this.resolveResult);
resolvePromise(promise2,fulfilledResult, resolve, reject);
};
this.onReject = () => {
const rejectedResult = onReject(this.rejectResult);
resolvePromise(promise2,rejectedResult, resolve, reject);
};
break;
case FULFILLED:
const fulfilledResult = onResolve(this.resolveResult);
resolvePromise(promise2,fulfilledResult, resolve, reject);
break;
default:
const rejectedResult = onReject(this.rejectResult);
resolvePromise(promise2,rejectedResult, resolve, reject);
break;
}
});
return promise2;
};
catch = onReject => {
this.then(null, onReject);
};
}
const resolvePromise = (result, resolve, reject) => {
resolve(result, "a");
};
const demo = new PromiseDemo((resolve, reject) => {
// resolve("sajdhgas1");
setTimeout(() => {
resolve("sajdhgas2");
}, 1000);
});
const a = demo
.then(a => {
console.log(a, "then1");
return "json.post";
})
.then(a => {
console.log(a, "then2");
});
複製代碼
功能:數組
function resolvePromise(promise2, x, resolve, reject) {
// 只返回onresolve的第一個then 防止屢次調用
let called;
if(x === promise2 ){
// reject報錯
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 若是是promise
if (x !== null && (typeof x === "function" || typeof x === "object")) {
try {
// 若是onresolve返回值x是一個promise 則x存在then方法
let then = x.then;
if (typeof then === "function") {
if (called) return;
called = true;
// 若是是promise 獲取promise.then 的返回值
// 再執行一遍resolvePromise 拋出結果給下一個then
/** * const a = new PromiseDemo((res,rej)=>{ res(222,'222') }) a.then.call(this,(a)=>{ console.log(a,'a') }) */
then.call(
x, // x是onReslove返回的 promise.then
res => {
// 獲取到onReslove 返回的promise.then的結果後調用resolvePromise 返回非promise的值
resolvePromise(promise2, res, resolve, reject);
},
err => {
reject(err);
}
);
} else {
resolve(x);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
}
複製代碼
我嘗試用下面的代碼驗證我寫的promise 鏈式調用順序 結果代碼報錯
這裏涉及到一個知識點 —— 鏈式調用順序promise
由於在同一個then內的回調callback都是被異步調用的, 因此同一級的then中先調用最外層then再向內層依次執行異步
new PromiseDemo((resolve, reject) => {
console.log("log: 外部promise");
resolve();
})
.then(() => {
console.log("log: 外部第一個then");
new PromiseDemo((resolve, reject) => {
console.log("log: 內部promise");
resolve();
})
.then(() => {
console.log("log: 內部第一個then");
})
.then(() => {
console.log("log: 內部第二個then");
});
})
.then(() => {
console.log("log: 外部第二個then");
});
// log: 外部promise
// log: 外部第一個then
// log: 內部promise
// log: 內部第一個then
// log: 外部第二個then
// log: 內部第二個then
複製代碼
下面是完整代碼async
const PENDING = "pending";
const FULFILLED = "fullilled";
const REJECTED = "rejected";
class PromiseDemo {
constructor(executor) {
this.state = PENDING;
this.resolveResult = undefined;
this.rejectResult = undefined;
this.onResolve = undefined;
this.onReject = undefined;
let resolve = resolveResult => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.resolveResult = resolveResult;
this.onResolve();
}
};
let reject = rejectResult => {
if (this.state === PENDING) {
this.state = REJECTED;
this.rejectResult = rejectResult;
this.onReject();
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then = (onResolve, onReject) => {
const promise2 = new PromiseDemo((resolve, reject) => {
switch (this.state) {
case PENDING:
this.onResolve = () => {
setTimeout(() => {
try {
const fulfilledResult = onResolve(this.resolveResult);
resolvePromise(fulfilledResult, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
};
this.onReject = () => {
setTimeout(() => {
try {
const rejectedResult = onReject(this.rejectResult);
resolvePromise(rejectedResult, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
};
break;
case FULFILLED:
setTimeout(() => {
try {
const fulfilledResult = onResolve(this.resolveResult);
resolvePromise(promise2, fulfilledResult, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
break;
default:
setTimeout(() => {
const rejectedResult = onReject(this.rejectResult);
resolvePromise(promise2,rejectedResult, resolve, reject);
}, 0)
break;
}
});
return promise2;
};
catch = onReject => {
this.then(null, onReject);
};
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError("Chaining cycle detected for promise"));
}
let called;
if (x != null && (typeof x === "object" || typeof x === "function")) {
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
err => {
if (called) return;
called = true;
reject(err);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
複製代碼
promise的實例 在同一級別能夠調用多個then 因此咱們要把resolve回調用數組的形式儲存函數
const PENDING = "pending";
const FULFILLED = "fullilled";
const REJECTED = "rejected";
class PromiseDemo {
constructor(executor) {
this.state = PENDING;
this.resolveResult = undefined;
this.rejectResult = undefined;
this.onResolve = [];
this.onReject = [];
let resolve = value => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.resolveResult = value;
// 把resolve回調用數組的形式儲存
this.onResolve.forEach(fn=>fn());
}
};
let reject = reason => {
if (this.state === PENDING) {
this.state = REJECTED;
this.rejectResult = reason;
this.onReject.forEach(fn=>fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then = (onResolve, onReject) => {
const promise2 = new PromiseDemo((resolve, reject) => {
switch (this.state) {
case PENDING:
// 把resolve回調用數組的形式儲存
this.onResolve.push(() => {
setTimeout(() => {
try {
const fulfilledResult = onResolve(this.resolveResult);
resolvePromise(fulfilledResult, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
this.onReject.push(() => {
setTimeout(() => {
try {
const rejectedResult = onReject(this.rejectResult);
resolvePromise(rejectedResult, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
break;
case FULFILLED:
setTimeout(() => {
try {
const fulfilledResult = onResolve(this.resolveResult);
resolvePromise(promise2, fulfilledResult, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
break;
default:
setTimeout(() => {
const rejectedResult = onReject(this.rejectResult);
resolvePromise(promise2, rejectedResult, resolve, reject);
}, 0);
break;
}
});
return promise2;
};
catch = onReject => {
this.then(null, onReject);
};
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError("Chaining cycle detected for promise"));
}
let called;
if (x != null && (typeof x === "object" || typeof x === "function")) {
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
err => {
if (called) return;
called = true;
reject(err);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
const p = new PromiseDemo((resolve, reject) => {
setTimeout(() => {
console.log("log: promise");
resolve();
}, 0);
});
p.then(() => {
console.log("log: promise1");
});
p.then(() => {
console.log("log: promise2");
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("log: 真實promise");
resolve();
}, 0);
});
p2.then(() => {
console.log("log: 真實promise1");
});
p2.then(() => {
console.log("log: 真實promise2");
});
複製代碼
promise.all 等到全部結果返回 再調用resolvepost
PromiseDemo.all = (promises) =>{
let results = [];
function processResult (data,index,res) {
results.push(data);
if(promises.length === (index + 1)){
res(results)
}
}
return new Promise((res,rej)=>{
try{
promises.forEach((promise,index)=>{
promise.then((result)=>{
processResult(result,index,res)
})
})
}catch(e){
rej(e)
}
})
}
複製代碼
promise.race 等到第一個結果就調用resolve
PromiseDemo.race = (promises) =>{
function processResult (data,res) {
if(data){
res(data)
}
}
return new Promise((res,rej)=>{
try{
promises.forEach((promise)=>{
promise.then((result)=>{
processResult(result,res)
})
})
}catch(e){
rej(e)
}
})
}
複製代碼
阮一峯 es6裏就有講
async function fn(args) {
// ...
}
// 等同於
function fn(args) {
return spawn(function* () {
// ...
});
}
複製代碼
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
複製代碼