簡體   English   中英

我的 Javascript promise 實現有什么問題?

[英]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.resultundefined 為什么會這樣,我該如何解決?

這是我的代碼:

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()通常以兩種不同的方式處理:

  1. promise 待定。 存儲傳遞給then()的回調,並在稍后解決 promise 時調用這些回調。
  2. promise 有一個結果(它已解決或被拒絕),在這種情況下,我們將盡快調用傳遞給 then 的回調。

您永遠不會處理案例 1,因此如果 promisethen()被調用后解析,它將不起作用。

此外,您從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草圖。 注意valueresolvedrejected是構造函數的參數,但它們應該是私有的。 這可以使用多種技術來完成,但為了簡單起見,我暫時保持這種方式。 調用者只打算傳遞第一個參數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.thenp.catch可用。 我們應該阻止用戶直接調用p.resolvep.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM