私たちの手書きのプロミスは主に次の機能を実装しています
-
初期化と非同期呼び出し
-
その後、チェーンコールをキャッチ
-
API .resolve .reject .all .race(基本的なpromise APIを実装します)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MyPromise</title>
</head>
<body>
<h1>MyPromise</h1>
<script src="./MyPromise.js"></script>
<script>
const p1 = new MyPromise((resolve, reject) => {
// resolve(100)
// reject('错误信息...')
setTimeout(() => {
resolve(100)
}, 1000)
})
// const p11 = p1.then(data1 => {
// console.log('data1', data1)
// return data1 + 1
// })
// const p12 = p11.then(data2 => {
// console.log('data2', data2)
// return data2 + 2
// })
// const p13 = p12.catch(err => console.error(err))
const p2 = MyPromise.resolve(200)
const p3 = MyPromise.resolve(300)
const p4 = MyPromise.reject('错误信息...')
// const p5 = MyPromise.all([p1, p2, p3]) // 传入 promise 数组,等待所有的都 fulfilled 之后,返回新 promise ,包含前面所有的结果
// p5.then(result => console.log('all result', result))
const p6 = MyPromise.race([p1, p2, p3]) // 传入 promise 数组,只要有一个 fulfilled 即可返回
p6.then(result => console.log('race result', result))
</script>
</body>
</html>
复制代码
約束の基礎
-
Promiseはクラスです
-
Promiseクラスが実行されると、すぐに実行されるエグゼキュータ関数が渡されます。
-
約束には3つの状態があります
- 保留中
- 満たされた
- 拒否されました
-
Promiseの状態は、一度決定されると変更できず、状態は次の方法でのみ決定できます。
- 保留中=>実行済み
- 保留中=>拒否
-
状態の変化は、resolveメソッドとrejectメソッドによって変更されます
-
thenメソッドが内部で行うのは、状態の判断です。
- Fulfilled状態の場合、正常なコールバックを実行します
- 拒否状態の場合は、失敗したコールバックを実行します
-
promiseを連鎖させるには、thenメソッドでPromiseインスタンスを返す必要があります
コード
/**
* @description MyPromise
* @author 双越
*/
class MyPromise {
state = 'pending' // 状态,'pending' 'fulfilled' 'rejected'
value = undefined // 成功后的值
reason = undefined // 失败后的原因
resolveCallbacks = [] // pending 状态下,存储成功的回调
rejectCallbacks = [] // pending 状态下,存储失败的回调
constructor(fn) {
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.rejectCallbacks.forEach(fn => fn(this.reason))
}
}
try {
fn(resolveHandler, rejectHandler)
} catch (err) {
rejectHandler(err)
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
fn2 = typeof fn2 === 'function' ? fn2 : (e) => e
if (this.state === 'pending') {
const p1 = new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
this.rejectCallbacks.push(() => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
})
return p1
}
if (this.state === 'fulfilled') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
return p1
}
if (this.state === 'rejected') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
return p1
}
}
// 就是 then 的一个语法糖,简单模式
catch(fn) {
return this.then(null, fn)
}
}
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => resolve(value))
}
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason))
}
MyPromise.all = function (promiseList = []) {
const p1 = new MyPromise((resolve, reject) => {
const result = [] // 存储 promiseList 所有的结果
const length = promiseList.length
let resolvedCount = 0
promiseList.forEach(p => {
p.then(data => {
result.push(data)
// resolvedCount 必须在 then 里面做 ++
// 不能用 index
resolvedCount++
if (resolvedCount === length) {
// 已经遍历到了最后一个 promise
resolve(result)
}
}).catch(err => {
reject(err)
})
})
})
return p1
}
MyPromise.race = function (promiseList = []) {
let resolved = false // 标记
const p1 = new Promise((resolve, reject) => {
promiseList.forEach(p => {
p.then(data => {
if (!resolved) {
resolve(data)
resolved = true
}
}).catch((err) => {
reject(err)
})
})
})
return p1
}
复制代码