2017-10-16 1 views
0

J'ai déjà posé la question trouvée ici: Retaining Data across multiple promise chainsNoeud Unhandled Promesse numéro

Je fini par utiliser T.J. La réponse de Crowder pour mon code de base a fait beaucoup de changements depuis. Mais j'ai remarqué quelque chose de bizarre dans le nœud que je n'arrive pas à surmonter. Je suis retourné au code de base qu'il a fourni et la question semble être là aussi.

Voici l'exemple:

"use strict"; 

// For tracking our status 
class Status { 
    constructor(total = 0, count = 0) { 
     this.id = ++Status.id; 
     this.total = total; 
     this.count = count; 
    } 
    addCall() { 
     ++this.total; 
     return this; 
    } 
    addProgress() { 
     ++this.count; 
     return this; 
    } 
    toString() { 
     return `[S${this.id}]: Total: ${this.total}, Count: ${this.count}`; 
    } 
} 
Status.id = 0; 

// The promise subclass 
class RepoPromise extends Promise { 
    constructor(executor) { 
     super(executor); 
     this.s = new Status(); 
    } 
    // Utility method to wrap `then`/`catch` callbacks so we hook into when they're called 
    _wrapCallbacks(...callbacks) { 
     return callbacks.filter(c => c).map(c => value => this._handleCallback(c, value)); 
    } 
    // Utility method for when the callback should be called: We track that we've seen 
    // the call then execute the callback 
    _handleCallback(callback, value) { 
     this.s.addProgress(); 
     console.log("Progress: " + this.s); 
     return callback(value); 
    } 
    // Standard `then`, but overridden so we track what's going on, including copying 
    // our status object to the new promise before returning it 
    then(onResolved, onRejected) { 
     this.s.addCall(); 
     console.log("Added: " + this.s); 
     const newPromise = super.then(...this._wrapCallbacks(onResolved, onRejected)); 
     newPromise.s = this.s; 
     return newPromise; 
    } 
    // Standard `catch`, doing the same things as `then` 
    catch(onRejected) { 
     this.s.addCall(); 
     console.log("Added: " + this.s); 
     const newPromise = super.catch(...this._wrapCallbacks(onRejected)); 
     newPromise.s = this.s; 
     return newPromise; 
    } 
} 

// Create a promise we'll resolve after a random timeout 
function delayedGratification() { 
    return new Promise(resolve => { 
     setTimeout(_ => { 
      resolve(); 
     }, Math.random() * 1000); 
    }); 
} 

// Run! Note we follow both kinds of paths: Chain and diverge: 
const rp = RepoPromise.resolve('Test'); 
rp.then(function(scope) { 
    return new Promise((resolve, reject) => { 
     console.log(' Rejected') 
     reject(scope) 
    }) 
}) 
.catch(e => {console.log('Never Makes it')}) 

quand je lance cela avec: node test.js-je obtenir la sortie suivante

Added: [S1]: Total: 1, Count: 0 
Added: [S1]: Total: 2, Count: 0 
Added: [S1]: Total: 3, Count: 0 
Progress: [S1]: Total: 3, Count: 1 
    Rejected 
(node:29364) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Test 
(node:29364) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 

Notez que le journal de la console pour "never makes it" n'est pas présent, notez aussi, je déjà résolu le problème avec catch en cours d'exécution deux fois car il est simple sucre syntaxique pour then(null, function(){}), de sorte que vous pouvez ignorer cela.

Pourquoi les prises ne fonctionnent-elles pas comme prévu? Quand je fais cela avec une promesse normale, il n'y a pas de problèmes, comme ci-dessous. Donc, je sais pour un fait que le _wrapCallbacks est à l'origine du problème, je ne sais pas exactement pourquoi, ou comment y remédier.

const rp = Promise.resolve('Test'); 
rp.then(function(scope) { 
    return new Promise((resolve, reject) => { 
     console.log(' Rejected') 
     reject(scope) 
    }) 
}) 
.catch(e => {console.log('Makes it')}) 

Répondre

1

La mise en œuvre catch de votre promesse ne fonctionne pas. Notez que le catch natif est implémenté en tant que return this.then(null, callback) - l'appel super.catch retournera directement à votre implémentation then.

Et votre implémentation then a un défaut majeur: il n'aime pas obtenir un argument null avant une fonction. Observez ce qui se passe dans l'appel ci-dessus lorsque vous faites ceci:

_wrapCallbacks(...callbacks) { 
    return callbacks.filter(c => c).map(…); 
//     ^^^^^^^^^^^^^^^ 
} 
then(onResolved, onRejected) { 
    … 
    const newPromise = super.then(...this._wrapCallbacks(onResolved, onRejected)); 
    … 
} 

Cela va tout simplement retirer le null du tableau d'arguments et de transmettre le rappel onrejected comme onfulfilled à la place. Vous aurez envie de laisser tomber le filter et utiliser un ternaire dans la fonction de mise en correspondance à la place:

_wrapCallbacks(...callbacks) { 
    return callbacks.map(c => typeof c == "function" 
     ? value => this._handleCallback(c, value) 
     : c); 
} 

vous pouvez simplement laisser tomber aussi la catch substituée.

+0

Oui, j'ai déjà laissé tomber la capture substituée, merci pour cela, j'étais toujours confus quant à la raison pour laquelle il a utilisé le filtre, mais je vois maintenant. C'était exactement mon problème, je savais que c'était quelque chose avec cette fonction. Je suppose que j'ai besoin de réapprendre le filtre/carte. MERCI! – Krum110487

+0

Tbh, je n'aurais pas utilisé 'filter' /' map' à tous, mais juste appelé 'super.then (this._wrapCallback (onFulfilled), this._wrapCallback (onRejected));' – Bergi

+0

D'accord, je viens de réaliser que je J'ai un malentendu fondamental sur les filtres/cartes, car je les utilise rarement, sachant que nul n'a été abandonné m'aurait aidé à comprendre ce qui se passait. – Krum110487