Promiseを手書きで書く(面接で十分)
24142 ワード
//
new Promise((resolve, reject) => {
setTimeout(() => resolve(new Promise(res => res(333))), 2000)
}).then(res => {
console.log(res)
return 222
}).then().then(res => {
console.log(res);
return new Promise(res => {
setTimeout(() => { res(666) }, 1000)
}).then(res => {
console.log(res);
return 999
})
}).then(res => {
console.log(res);
})
/*
* :
* 333
* 222
* 666
* 999
*/
//
;(function (global) {
global.Promise = Promise
// promise
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(fn) {
this.state = PENDING
this.fulfilledQueue = []
this.rejectedQueue = []
try {
fn(
// this
(res) => {
this._resolve(res)
},
(err) => {
this._reject(err)
}
// this.resolve.bind(this), this.reject.bind(this))
)
} catch (e) {
reject(e)
}
}
Promise.prototype = {
constructor: Promise,
_resolve: function (value) {
if (value instanceof Promise) {
return value.then(
// this
(res) => {
this._resolve(res)
},
(err) => {
this._reject(err)
}
)
}
setTimeout(() => {
if (this.state === PENDING) {
this.state = FULFILLED
this.value = value
this.fulfilledQueue.forEach((fn) => fn(this.value))
}
})
},
_reject: function (value) {
setTimeout(() => {
if (this.state === PENDING) {
this.state = REJECTED
this.value = value
this.rejectedQueue.forEach((fn) => fn(this.value))
}
})
},
then: function (fulfilled, rejected) {
this.fulfilled =
typeof fulfilled === 'function' ? fulfilled : (v) => v
this.rejected =
typeof rejected === 'function'
? rejected
: (err) => {
throw err
}
if (this.state === PENDING) {
return new Promise((resolve, reject) => {
this.fulfilledQueue.push(() => {
try {
this.value = this.fulfilled(this.value)
resolve(this.value)
} catch (error) {
reject(error)
}
})
this.rejectedQueue.push(() => {
try {
this.value = this.rejected(this.value)
resolve(this.value)
} catch (error) {
reject(error)
}
})
})
}
if (this.state === FULFILLED) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
this.value = this.fulfilled(this.value)
resolve(this.value)
} catch (error) {
reject(error)
}
})
})
}
if (this.state === REJECTED) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
this.value = this.rejected(this.value)
resolve(this.value)
} catch (error) {
reject(error)
}
})
})
}
},
}
})(window)