2016-05-03 9 views
1

Ich verwende Node.js und die Bluebird verspricht Bibliothek.Wie kann ich diese Funktionen promisifizieren?

Dieser Code funktioniert genau so, wie ich will:

/* 
* Try using Bluebird promisify(): 
* - "Good" case: this works perfectly. 
* ... but it DOESN'T use "promisify()"; it creates a new promise for each function. 
* - SAMPLE OUTPUT: 
*  callABC()... 
*  a(): [ 'a' ] 
*  b(): [ 'a', 'b' ] 
*  c(): [ 'a', 'b', 'c' ] 
*  Done: results: [ 'a', 'b', 'c' ] 
*/ 
var Promise = require('bluebird'); 

var a = function (results) { 
    return new Promise(function(resolve, reject) { 
    setTimeout(function() { 
     results.push("a"); 
     console.log("a(): ", results); 
     resolve(results); 
    }, 15); 
    }); 
} 

var b = function (results) { 
    return new Promise(function(resolve, reject) { 
    setTimeout(function() { 
     results.push("b"); 
     console.log("b(): ", results); 
     resolve(results); 
    }, 5); 
    }); 
} 

var c = function (results) { 
    return new Promise(function(resolve, reject) { 
    setTimeout(function() { 
     results.push("c"); 
     console.log("c(): ", results); 
     resolve(results); 
    }, 10); 
    }); 
} 


var callABC = function (results) { 
    console.log("callABC()..."); 
    a(results) 
    .then(b) 
    .then(c) 
    .then(function (results) { 
    console.log("Done: results:", results); 
    }) 
    .catch(function (err) { 
    console.log("Error:", err); 
    }); 
} 

callABC([]); 

Ich verstehe, dass Sie Ihre eigenen Versprechungen wie diese manuell instanziieren kann "schlecht" in Betracht gezogen werden:

F: Wie kann ich das obige Snippet "Promistifizieren"?

Ich habe viele Dinge ausprobiert; keiner von ihnen hat gearbeitet. Zum Beispiel:

/* 
* Try using Bluebird promisify(): 
* - Fails: never calls b() or c() 
*/ 
var Promise = require('bluebird'); 

var a = Promise.promisify(function (results) { 
    setTimeout(function() { 
    results.push("a"); 
    console.log("a(): ", results); 
    }, 15); 
}); 

var b = Promise.promisify(function (results) { 
    setTimeout(function() { 
    results.push("b"); 
    console.log("b(): ", results); 
    }, 5); 
}); 

var c = Promise.promisify(function (results) { 
    setTimeout(function() { 
    results.push("c"); 
    console.log("c(): ", results); 
    }, 10); 
}); 

var callABC = function (results) { 
    console.log("callABC()..."); 
    a(results) 
    .then(b) 
    .then(c) 
    .then(function (results) { 
    console.log("Done: results:", results); 
    }) 
    .catch(function (err) { 
    console.log("Error:", err); 
    }); 
} 

callABC([]); 

Q: Was ist der richtige Weg, um das erste Beispiel "Promisify"?

F: Insbesondere, wie kann ich „resolve()“ oder „ablehnen()“ meine Rückrufe, wenn ich die automatisierte Promise.promisify() oder Promise.promisifyAll() für die manuelle new Promise() ersetzen? Ich stelle mir vor "throw" ruft .catch() auf, aber gibt es einen anderen (besseren?) Mechanismus?

Frage: Gibt es Einschränkungen? Muss die Funktion beispielsweise einen Callback-Parameter haben, um "promisifiziert" zu werden?

+2

'Promisify' macht keine Magie. Es funktioniert nur für Funktionen, die Rückrufe nehmen. Siehe [Wie konvertiere ich eine bestehende Callback-API in Versprechen?] (Http://stackoverflow.com/q/22519784/1048572) für gute Anwendungsfälle. – Bergi

+1

Der richtige Weg, um dieses spezielle Problem zu lösen, ist 'Promise.delay' zu verwenden, was die promitierte Version von' setTimeout' ist. Versuch es. – Bergi

+0

@Bergi: 1) Dies ist die Antwort, die ich gesucht habe "Promisify macht keine Magie. Es funktioniert nur für Funktionen, die Callbacks nehmen". 2) Danke für den Link. 3) "setTimeout()" war nur für Testzwecke; Es hat nichts mit der eigentlichen Frage zu tun. 4) Wenn Sie Ihren Kommentar in eine "Antwort" setzen möchten, würde ich gerne "akzeptieren". – paulsm4

Antwort

0

Die Antwort lautet: "Nicht alle JS-Funktionen können promitifiziert werden". Im Einzelnen:

http://bluebirdjs.com/docs/api/promise.promisify.html

Promise.promisify) ... gibt eine Funktion, die die gegebenen nodeFunction einbettet. Anstatt einen Rückruf zurückzunehmen, gibt die zurückgegebene Funktion eine Zusage zurück, deren Schicksal durch das Rückrufverhalten der gegebenen Knotenfunktion entschieden wird. Die Knotenfunktion sollte der node.js-Konvention zum Akzeptieren eines Rückrufs als letztes Argument und zum Aufrufen des Rückrufs mit Fehler als erstes Argument und als Erfolgswert für das zweite Argument entsprechen.

Also im obigen Beispiel ist "New Promise" der richtige Ansatz: "Promise.promisify()" wird nicht funktionieren.

Verwandte Themen