[英]What is wrong with my Javascript promise implementation?
我正在嘗試構建自己的 Promise 以提高我對 javascript 中 Promise 的理解。 我目前被困在.then
方法上,我想問一下:在 .then 的文檔中.then
這里的https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise /then ,它表示then
方法返回 Promise。 我在寫這篇文章時遇到了困難,因為看起來this.result
是undefined
。 為什么會這樣,我該如何解決?
這是我的代碼:
class LitePromise {
constructor(fn) {
if (typeof fn !== "function") {
throw new TypeError("Promises have to be functions");
}
this.fn = fn;
this.state = PENDING;
this.result = null;
const resolveCallback = this.resolve.bind(this);
const rejectCallback = this.reject.bind(this);
try {
fn(resolveCallback, rejectCallback);
} catch (err) {
this.reject(err);
}
}
resolve(arg) {
console.log(arg, "arg");
this.result = arg;
this.state = RESOLVED;
}
reject() {
this.state = REJECTED;
}
// make an instance of this promise
then(callback) {
const tinyPromise = new LitePromise(this.fn);
console.log(callback, "callback");
try {
return tinyPromise.resolve(callback(this.result));
} catch {
return tinyPromise.reject(callback(this.result));
}
}
}
console.log("------------------");
const yaypromise = new LitePromise((resolve, reject) => {
console.log("1. running");
setTimeout(() => {
console.log("2. resolving");
resolve("yay");
}, 100);
}).then((result) => {
console.log("3. evaluating");
if (result !== "yay") {
console.log("Is not working yet");
return;
}
console.log("SUCCESS!", result);
});
我認為這里的核心問題如下。 then()
通常以兩種不同的方式處理:
then()
的回調,並在稍后解決 promise 時調用這些回調。 您永遠不會處理案例 1,因此如果 promise在then()
被調用后解析,它將不起作用。
此外,您從then()
返回的子 promise 本身應該解決傳遞給then()
的回調的結果完成。
如果這聽起來非常令人困惑,那是因為這很難 =) 我建議先嘗試讓您的邏輯正確,以便僅處理.then .then()
中的回調,並且不要從.then()
返回任何內容。
出於同樣的原因,我還制作了自己的 promise。 它非常小,也許它有幫助:
https://github.com/evert/promise-demo/blob/master/src/my-promise.js
這是我們希望與promise
一起使用的示例程序; 注意小寫的p
-
const delay = ms =>
new promise(r => setTimeout(r, ms))
const roll = n =>
{ console.log("rolling...")
return delay(1000)
.then(_ => Math.ceil(Math.random() * n))
.then(x => { console.log(x); return x })
}
const main = _ =>
roll(20).then(x =>
roll(20).then(y =>
roll(20).then(z =>
{ console.log("three rolls:", x, y, z)
return [x,y,z]
}
)
)
)
main()
.then(([x,y,z]) => x + y + z)
.then(sum => console.log("sum:", sum))
.catch(console.error)
rolling...
12
rolling...
18
rolling...
15
three rolls: 12 18 15
sum: 45
正如其他人評論的那樣,您的代碼中有很多需要修復的地方。 但是不要感覺不好,因為 Promise 並不是特別容易實現。 這是我的第一個promise
草圖。 注意value
、 resolved
、 rejected
是構造函數的參數,但它們應該是私有的。 這可以使用多種技術來完成,但為了簡單起見,我暫時保持這種方式。 調用者只打算傳遞第一個參數exec
-
class promise
{ constructor(exec, value, resolved = false, rejected = false)
{ this.value = value
this.resolved = resolved
this.rejected = rejected
this.callback = []
if (this.resolved || this.rejected) return
exec(x => this.resolve(x), e => this.reject(e))
}
resolve(value)
{ if (this.resolved || this.rejected) return
let p = promise.resolve(value)
for (const [ifResolved, ifRejected] of this.callback)
p = p.then(ifResolved, ifRejected)
Object.assign(this, p)
}
reject(value)
{ if (this.resolved || this.rejected) return
let p = promise.reject(value)
for (const [ifResolved, ifRejected] of this.callback)
p = p.then(ifResolved, ifRejected)
Object.assign(this, p)
}
then(ifResolved, ifRejected = promise.reject)
{ if (this.resolved)
{ try
{ return promise.resolve(ifResolved(this.value)) }
catch (err)
{ return promise.reject(err) }
}
else if (this.rejected)
{ try
{ return promise.resolve(ifRejected(this.value)) }
catch (err)
{ return promise.reject(err) }
}
else
{ this.callback.push([ifResolved, ifRejected])
return this
}
}
catch(ifRejected)
{ return this.then(value => value, ifRejected) }
static resolve(value)
{ return (value instanceof promise)
? value
: new promise(_ => {}, value, true, false)
}
static reject(value)
{ return (value instanceof promise)
? value
: new promise(_ => {}, value, false, true)
}
}
與 Promise 一樣,在promise
對象上應該只有p.then
和p.catch
可用。 我們應該阻止用戶直接調用p.resolve
或p.reject
,但是現在它可以很容易地看到事情是如何工作的。 The class functions promise.resolve
and promise.reject
are analogous to Promise.resolve
and Promise.reject
.
展開下面的代碼片段以在您自己的瀏覽器中驗證結果 -
class promise { constructor(exec, value, resolved = false, rejected = false) { this.value = value this.resolved = resolved this.rejected = rejected this.callback = [] if (this.resolved || this.rejected) return exec(x => this.resolve(x), e => this.reject(e)) } resolve(value) { if (this.resolved || this.rejected) return let p = promise.resolve(value) for (const [ifResolved, ifRejected] of this.callback) p = p.then(ifResolved, ifRejected) Object.assign(this, p) } reject(value) { if (this.resolved || this.rejected) return let p = promise.reject(value) for (const [ifResolved, ifRejected] of this.callback) p = p.then(ifResolved, ifRejected) Object.assign(this, p) } then(ifResolved, ifRejected = promise.reject) { if (this.resolved) { try { return promise.resolve(ifResolved(this.value)) } catch (err) { return promise.reject(err) } } else if (this.rejected) { try { return promise.resolve(ifRejected(this.value)) } catch (err) { return promise.reject(err) } } else { this.callback.push([ifResolved, ifRejected]) return this } } catch(ifRejected) { return this.then(value => value, ifRejected) } static resolve(value) { return (value instanceof promise)? value: new promise(_ => {}, value, true, false) } static reject(value) { return (value instanceof promise)? value: new promise(_ => {}, value, false, true) } } const delay = ms => new promise(r => setTimeout(r, ms)) const roll = n => { console.log("rolling...") return delay(1000).then(_ => Math.ceil(Math.random() * n)).then(x => { console.log(x); return x }) } const main = _ => roll(20).then(x => roll(20).then(y => roll(20).then(z => { console.log("three rolls:", x, y, z) return [x,y,z] } ) ) ) main().then(([x,y,z]) => x + y + z).then(sum => console.log("sum:", sum)).catch(console.error)
明天我會回來添加一個示例來演示錯誤並回答任何問題(如果有的話)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.