web-dev-qa-db-de.com

Was ist der Unterschied zwischen auflösen (thenable) und auflösen ('non thenable-object')?

Ich habe versucht, den Unterschied zwischen resolve(thenable) und resolve('non-thenable-object') zu verstehen.

Verwenden Sie in den folgenden Beispielen Versprechen anstelle von thenable, da Versprechen auch thenable ist und möglicherweise einfacher zu verstehen ist.

Demo1: resolve(promise)

let resolvePromise = new Promise(resolve => {
  let resolvedPromise = Promise.resolve()
  resolve(resolvedPromise)
})
resolvePromise.then(() => {
  console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
  console.log('promise1')
})
resolvedPromiseThen
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })

Ergebnis: 

  • versprechen1
  • versprechen2
  • resolPromise behoben
  • versprechen3

Demo2: resolve('non-thenable-object')

let resolvePromise = new Promise(resolve => {
  resolve('non-thenable-object')
})
resolvePromise.then(() => {
  console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
  console.log('promise1')
})
resolvedPromiseThen
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })

Ergebnis: 

  • resolPromise behoben
  • versprechen1
  • versprechen2
  • versprechen3

Also überprüfte ich die Spezifikation und fand Promise Resolve Functions . Dann kam zu PromiseResolveThenableJob und EnqueueJob .

Entsprechend der Spezifikation denke ich, dass demo1 so war 

Demo3:

let resolvePromise = new Promise(resolve => {
  let resolvedPromise = Promise.resolve()
 // resolve(resolvedPromise)
  // works like 
  Promise.resolve().then(() => {
    Promise.resolve(resolvedPromise).then(() => {
      resolve()
   })
  })
})
resolvePromise.then(() => {
  console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
  console.log('promise1')
})
resolvedPromiseThen
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })

Ich denke schon, weil Promise Resolve Functions sagt:

  1. Führen Sie EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, "Versprechen, Auflösung, dann Aktion") aus.

Und PromiseResolveThenableJob sagt:

Dieser Job verwendet die bereitgestellte Thenable und seine Then-Methode, um das gegebene Versprechen zu lösen. Dieser Prozess muss als Job erfolgen, um sicherzustellen, dass die Auswertung der then-Methode erfolgt, nachdem die Bewertung von umgebendem Code abgeschlossen ist.

Ich denke auch, dass demo2 funktioniert

Demo4:

//let resolvePromise = new Promise(resolve => {
  //resolve('str')
//})
//works like
let resolvePromise = Promise.resolve('str')

resolvePromise.then(() => {
  console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
  console.log('promise1')
})

resolvedPromiseThen
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })

Wie die Promise Resolve-Funktionen sagt:

Wenn IsCallable (thenAction) falsch ist, geben Sie FulfillPromise zurück (Versprechen, Auflösung).

Obwohl die Ergebnisse zwischen Demo1 -Demo3 und Demo2 -Demo4 gleich sind, bin ich immer noch nicht sicher, ob ich Recht hatte. Also bin ich hier um zu fragen

ob meine Logik stimmt? Wenn nicht, wie erklären Sie sich die verschiedenen Aufträge zwischen resolve(thenable) und resolve(non-thenable)?

5
xianshenglu

Ja, deine Logik sieht gut aus.

new Promise(resolve => resolve('non-thenable-object')) ist für alle Zwecke äquivalent zu Promise.resolve('non-thenable-object').

In Ihrer Demo3 würde ich jedoch empfehlen, Promise.resolve(resolvedPromise) wegzulassen. Ich bin nicht sicher, ob das beabsichtigt war oder nicht, aber Promise.resolve hat eine Verknüpfung, wenn sein Argument bereits ein Versprechen ist, und gibt dann die resolvedPromise wie sie ist. Du schreibst lieber

new Promise((resolve, reject) => {
  let resolvedPromise = Promise.resolve();
  // resolve(resolvedPromise) works like 
  Promise.resolve().then(() => resolvedPromise.then(resolve, reject));
});
2
Bergi

Nachdem ich die Spezifikation viele Male gelesen und getestet hatte, dachte ich, ich könnte sie bekommen.

Bevor wir anfangen, müssen wir etwas regeln.

nennen wir es RESOLVE(), wenn Sie resolve in Promise executor verwenden. Zum Beispiel bedeutet RESOLVE(thenable) den Code wie folgt:

  new Promise((resolve,reject)=>{
    resolve(thenable)
  })

während resolve(thenable) bedeutet Promise.resolve(thenable)

Ok, lass uns anfangen.

Promise.resolve('non-thenable') und RESOLVE('non-thenable')

Wenn wir Promise.resolve('non-thenable') verwenden, kommt es zu Promise.resolve

enter image description here

Dann kommt es zu PromiseResolve

enter image description here

Dort wurde Promise.resolve('non-thenable') transformiert

new Promise(resolve=>{
  resolve('non-thenable')
})

Wir haben also die Schlussfolgerung:

Promise.resolve('non-thenable') kann in RESOLVE('non-thenable') umgewandelt werden


RESOLVE(thenable)

demo1

let resolveThenable = new Promise((resolve, reject) => {
  let thenable = {
    then: function (resolve, reject) {
      console.log('in thenable')
      resolve(42)
    }
  }
  resolve(thenable)
  // works like
  // Promise.resolve().then(() => {
  //   thenable.then(resolve)
  // })
  // should be ?
  // Promise.resolve().then(() => {
  //   thenable.then.[[Value]](resolve)
  // })
  // equivalent to?
  // Promise.resolve().then(() => {
  //   thenable.then(resolve)
  // })
})
resolveThenable.then(() => {
  console.log('resolveThenable resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
  console.log('promise1')
})
resolvedPromiseThen
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })

// 'in thenable'
// 'promise1'
// 'resolveThenable resolved'
// 'promise2'
// 'promise3'

Nach Promise Resolve Functions , als wir RESOLVE(thenable) verwendeten, kommt es zu

enter image description here

Dann kommt es zu PromiseResolveThenableJob

enter image description here

Dies würde dazu führen, dass RESOLVE(thenable) wie folgt funktioniert

  Promise.resolve().then(() => {
    thenable.then.[[Value]](resolve)
  })

Also dachte ich es ist äquivalent zu

  Promise.resolve().then(() => {
    thenable.then(resolve)
  })

Welches hat das gleiche Ergebnis wie RESOLVE(thenable).

Wir können also sagen, dass RESOLVE(thenable) in transformiert werden kann

  Promise.resolve().then(() => {
    thenable.then(resolve)
  })
let resolvePromise = new Promise((resolve, reject) => {
  let resolvedPromise = Promise.resolve()
  resolve(resolvedPromise)
  // works like
  // Promise.resolve().then(() => {
  //   resolvedPromise.then(() => {
  //     resolve()
  //   })
  // })
  // should be?
  // Promise.resolve().then(() => {
  //   resolvedPromise.then.[[Value]](resolve,reject)
  // })
  // equivalent to ?
  // Promise.resolve().then(() => {
  //   resolvedPromise.then(resolve)
  // })
  // equivalent to ?
  // Promise.resolve().then(() => {
  //   resolvedPromise.then(() => {
  //     resolve()
  //   })
  // })
})
resolvePromise.then(() => {
  console.log('resolvePromise resolved')
})
let resolvedPromiseThen = Promise.resolve().then(res => {
  console.log('promise1')
})
resolvedPromiseThen
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })

// 'promise1'
// 'promise2'
// 'resolvePromise resolved'
// 'promise3'

Wenn wir über RESOLVE(resolvedPromise) gesprochen haben, können wir feststellen, dass die Spezifikation thenable nicht von promise unterscheidet. Auf die gleiche Weise kann RESOLVE(resolvedPromise) in umgewandelt werden

  Promise.resolve().then(() => {
    resolvedPromise.then(resolve)
  })

In diesem Fall ist die Reihenfolge zwischen RESOLVE(thenable) und RESOLVE(promise) unterschiedlich. Weil thenable.then Eine Synchronisierungsoperation ist, während resolvedPromise.then Eine asynchrone Operation ist. Sie sind nicht die gleiche then Methode.

Also, hier ist unser Fazit:

Sowohl RESOLVE(thenable) als auch RESOLVE(promise) können in umgewandelt werden

 new Promise((resolve, reject) => {
      Promise.resolve().then(() => {
        thenable.then(resolve)
      })
 })

Promise.resolve (thenable)

Bei Verwendung von Promise.resolve(promise) ist dies recht einfach, da das Argument promise zurückgegeben wird.

Bei der Verwendung von Promise.resolve(thenable) wird es jedoch kompliziert, und das thenable ist kein Versprechen. Nennen wir es Promise.resolve(nonPromiseThenable).

Nach Promise.resolve (x)

enter image description here

Dann kommt es zu

enter image description here

Also kann Promise.resolve(nonPromiseThenable) in umgewandelt werden

 new Promise(resolve => { 
   resolve(nonPromiseThenable)
 })

Und schließlich kommt zu

 new Promise(resolve => { 
   Promise.resolve().then(() => { 
     nonPromiseThenable.then(resolve) 
   }) 
 })

Sie können es in der Demo unten testen.

var thenable = {
  then(resolve, reject) {
    resolve(1)
  }
}
// code transformation 
Promise.resolve(thenable).then(res => {
  console.log(res)
})
// equal 
// new Promise(resolve => { 
//   resolve(thenable) 
// }).then(res => { 
//   console.log(res) 
// }) 
// equal 
// new Promise(resolve => { 
//   Promise.resolve().then(() => { 
//     thenable.then(resolve) 
//   }) 
// }).then(res => { 
//   console.log(res) 
// }) 

new Promise(resolve => resolve(2))
  .then(res => {
    console.log(res)
  })
  .then(res => console.log(3))

Lassen Sie uns zum Schluss einen Schluss ziehen:

  • Promise.resolve('nonThenable') kann in RESOLVE('nonThenable') umgewandelt werden. Sie haben die gleichen Wirkungen.
  • Promise.resolve(thenable) unterscheidet sich von RESOLVE(thenable). Sie haben unterschiedliche Wirkungen.
  • RESOLVE(thenable) und RESOLVE(promise) können in new Promise((resolve, reject) => { Promise.resolve().then(() => { thenable.then(resolve) }) }) umgewandelt werden
  • Promise.resolve(promise) === promise while Promise.resolve(nonPromiseThenable) kann in new Promise(resolve => { Promise.resolve().then(() => { nonPromiseThenable.then(resolve) }) }) umgewandelt werden
0
xianshenglu