Disons que de jeter à l'intérieur d' then()
rappel rejette le résultat de la promesse par un échec, et le retour à partir de then()
rappel remplit le résultat promesse avec une valeur de succès.
let p2 = p1.then(() => {
throw new Error('lol')
})
// p2 was rejected with Error('lol')
let p3 = p1.then(() => {
return 42
})
// p3 was fulfilled with 42
Mais parfois, même à l'intérieur de la poursuite, nous ne savons pas si nous avons réussi ou pas. Nous avons besoin de plus de temps.
return checkCache().then(cachedValue => {
if (cachedValue) {
return cachedValue
}
// I want to do some async work here
})
Toutefois, si je ne async y travailler, il serait trop tard pour return
ou throw
, ne serait-il pas?
return checkCache().then(cachedValue => {
if (cachedValue) {
return cachedValue
}
fetchData().then(fetchedValue => {
// Doesn't make sense: it's too late to return from outer function by now.
// What do we do?
// return fetchedValue
})
})
C'est pourquoi les Promesses ne serait pas utile si vous ne pouvait pas se résoudre à une autre Promesse.
Cela ne signifie pas que dans votre exemple, p2
serait devenue p3
. Ils sont séparés Promesse d'objets. Toutefois, en retournant p2
de then()
qui produit p3
que vous dites "je veux p3
se résoudre à ce que p2
résout, qu'elle réussisse ou échoue".
Comme pour la façon dont cela se produit, il est spécifique à l'implémentation. En interne, vous pouvez penser à de la then()
que la création d'une nouvelle Promesse. La mise en œuvre seront en mesure de remplir ou de le rejeter à chaque fois qu'il aime. Normalement, il va automatiquement remplir ou de le rejeter, lors de votre retour:
// Warning: this is just an illustration
// and not a real implementation code.
// For example, it completely ignores
// the second then() argument for clarity,
// and completely ignores the Promises/A+
// requirement that continuations are
// run asynchronously.
then(callback) {
// Save these so we can manipulate
// the returned Promise when we are ready
let resolve, reject
// Imagine this._onFulfilled is an internal
// queue of code to run after current Promise resolves.
this._onFulfilled.push(() => {
let result, error, succeeded
try {
// Call your callback!
result = callback(this._result)
succeeded = true
} catch (err) {
error = err
succeeded = false
}
if (succeeded) {
// If your callback returned a value,
// fulfill the returned Promise to it
resolve(result)
} else {
// If your callback threw an error,
// reject the returned Promise with it
reject(error)
}
})
// then() returns a Promise
return new Promise((_resolve, _reject) => {
resolve = _resolve
reject = _reject
})
}
Encore une fois, c'est beaucoup de pseudo-code, mais montre l'idée derrière l' then()
pourrait être mise en œuvre dans la Promesse implémentations.
Si nous voulons ajouter le support pour la résolution d'une Promesse, nous avons juste besoin de modifier le code afin de bénéficier d'une branche spéciale si l' callback
vous passez then()
retourné une Promesse:
if (succeeded) {
// If your callback returned a value,
// resolve the returned Promise to it...
if (typeof result.then === 'function') {
// ...unless it is a Promise itself,
// in which case we just pass our internal
// resolve and reject to then() of that Promise
result.then(resolve, reject)
} else {
resolve(result)
}
} else {
// If your callback threw an error,
// reject the returned Promise with it
reject(error)
}
})
Permettez-moi de préciser à nouveau que ce n'est pas une Promesse de la mise en œuvre et a de grands trous et des incompatibilités. Cependant, il devrait vous donner une idée intuitive de la façon dont la Promesse des bibliothèques de mettre en œuvre la résolution d'une Promesse. Après vous êtes à l'aise avec l'idée, je vous recommande de jeter un oeil à la façon dont les Promesses implémentations de gérer cela.