2017-12-28 11 views
1

meinen Code:unterschiedlich zwischen Rückruf und Versprechen in node.js

const readline = require('readline'); 

function scan(callback) { 
    const rl = readline.createInterface({ 
     input: process.stdin, 
     output: process.stdout, 
     prompt: '> ', 
    }); 

    rl.prompt(); 
    rl.on('line', (line) => { 
     callback(line); 
     rl.close(); 
    }).on('close',() => { 
     process.exit(0); 
    }); 
} 

scan(data => { 
    console.log('data: ', data); // can console 
}); 

I Rückruf verwendet und es kann Daten-Konsole, die u-Eingang, aber es wird nicht trösten, wenn ich Versprechen verwenden:

function scan() { 
    return new Promise((resolve, reject) => { 
     const rl = readline.createInterface({ 
      input: process.stdin, 
      output: process.stdout, 
      prompt: '> ', 
     }); 

     rl.prompt(); 
     rl.on('line', (line) => { 
      resolve(line); 
      rl.close(); 
     }).on('close',() => { 
      process.exit(0); 
     }); 
    }); 
} 

scan().then(data => { 
    console.log('data: ', data); // can not console 
}); 

was ist aufgetreten, was unterscheidet Callback und Promise?

+0

mögliche Dubletten [Arent-Versprechungen-nur-Rückrufe] (https://stackoverflow.com/questions/22539815/arent-promises-just-callbacks) – cometguy

+1

Mögliche Duplikate von [Versprechungen nicht nur Rückrufe?] (Https://stackoverflow.com/questions/22539815/arent-promises-just-callbacks) – cometguy

+0

@cometguy Ich lese es, aber ich denke, es ist keine Antwort auf meine Frage. – Rife

Antwort

0

Stack- und Warteschlangenproblem, Ihr Callback befindet sich auf dem gleichen Stack wie rl.close, aber der Resolve-Handler ist nicht (dieser ist in der Warteschlange).

Zum Beispiel:

new Promise(resolve=>resolve()) 
 
.then(_=>console.log("last"))//resolve handler is going on queue 
 
console.log("first")//this is on the same stack so logs 
 
//nothing more on the stack so get stuff from queue

einfache Lösung wäre, die nahe an der que nach resolve Handler zu setzen, die protokolliert:

function scan() { 
    return new Promise((resolve, reject) => { 
     const rl = readline.createInterface({ 
      input: process.stdin, 
      output: process.stdout, 
      prompt: '> ', 
     }); 

     rl.prompt(); 
     rl.on('line', (line) => { 
      resolve(line); 
      //put close on queue 
      Promise.resolve() 
      .then(
      _=>rl.close() 
     ); 
     }).on('close',() => { 
      process.exit(0); 
     }); 
    }); 
} 

scan().then(data => { 
    console.log('data: ', data); // can not console 
}); 

Stack und Queue video oder ducumentation

+0

Stapel? Warteschlange? Meinst du Stapel und Heap? – Bergi

+0

@Bergi-Stapel wie in [callstack] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Stack) Warteschlange wie in Ereignisschleife oder [Nachrichtenwarteschlange] (https: // developer .mozilla.org/de-DE/docs/Web/JavaScript/EventLoop # Queue) – HMR

+0

@Bergi Vielleicht wäre es korrekter zu sagen, dass die Resolve-Handler-Funktion nicht im aktuellen Call-Stack, sondern im Heap gespeichert ist und aufgerufen wird, wenn eine zugehörige Nachricht erstellt wird aus der Warteschlange, da diese Funktion diese Nachricht verarbeiten soll. Nachrichten werden erst aus der Warteschlange genommen, wenn der Aufrufstapel leer ist, so dass rs.close() und die on close-Handler zuerst aufgerufen werden. Wenn das 'readline'-Paket anders implementiert wurde, kann der close-Handler nach dem resolve-Handler aufgerufen werden (zum Beispiel: hat ein Timeout, um den Call-Stack zu löschen und zu einer anderen Nachricht zu liefern). – HMR

0

Für eine detailliertere Antwort siehe HMR's Antwort.

Anscheinend rufen Sie rl.close() gleich nach der Auflösung der Versprechen. Schauen Sie sich Ihren Event-Handler an:

process.exit(0); 

Offensichtlich stoppt es alle Ausführungen und beendet Ihr Programm. Event, obwohl Ihr Versprechen gelöst wird, wird exit schneller aufgerufen (Normales Verhalten mit der Event-Schleife).

So, um Ihr Problem zu lösen: Entfernen Sie den Ereignishandler on close. Nachdem jedes Versprechen gelöst wurde, wird Ihr Programm ordnungsgemäß beendet.

+1

Das erklärt es aber nicht, der Callback hat auch 'process.exit (0)' im close-Handler. Das Problem ist, dass 'resolve()' schließlich resolveHandler aus der Warteschlange aufrufen wird, so dass der nächste im Stapel 'rl.colse()' ist. Dies geschieht nicht mit dem Callback, Aufruf des Callbacks und 'rl.close()' sind gleicher Stapel. – HMR

Verwandte Themen