in Q

2014-03-27 3 views
36

Mit QI ein neues Versprechen definieren:in Q

var queue = q(); 

Aber mit Drossel, wenn ich tun:

var queue = new Promise(); 

ich:

TypeError: the promise constructor requires a resolver function 

Wie kann ich das gleiche Ergebnis wie mit Q erzielen?

Dies ist ein Ausschnitt aus meinem Code:

var queue = q() 
    promises = []; 
queue = queue.then(function() { 
    return Main.gitControl.gitAdd(fileObj.filename, updateIndex); 
}); 
// Here more promises are added to queue in the same way used above... 
promises.push(queue); 
return Promise.all(promises).then(function() { 
    // ... 
}); 
+1

FYI die 'q' Funktion ist die gleiche wie' Promise.cast' während 'Promise' Funktion ist die gleiche wie' q.promise' . Also ist das Äquivalent von 'q()' 'Promise.cast()' – Esailija

Antwort

22
var resolver = Promise.defer(); 
setTimeout(function() { 
    resolver.resolve(something); // Resolve the value 
}, 5000); 
return resolver.promise; 

Diese Linie ziemlich oft in den documentation verwendet wird.

Beachten Sie, dass dies in der Regel ein Anti-Pattern ist, das zu verwenden. Aber wenn Sie wissen, was Sie tun, ist Promise.defer() eine Möglichkeit, den Resolver zu erhalten, der ähnlich wie Q ist.

Es wird jedoch davon abgeraten, diese Methode zu verwenden. Bluebird hat es sogar abgeschrieben.

Stattdessen sollten Sie auf diese Weise verwenden:

return new Promise(function(resolve, reject) { 
    // Your code 
}); 

Siehe die entsprechenden Bits Dokumentation: Promise.defer() und new Promise().

Nach der Aktualisierung Ihrer Frage, hier ist Ihr Problem: Sie verwenden das gleiche Versprechen, um mehrere Werte zu lösen. Ein Versprechen kann nur einmal gelöst werden. Es bedeutet, dass Sie Promise.defer() so oft verwenden müssen, wie Sie versprechen.

Das heißt, nachdem Sie mehr von Ihrem Code gesehen haben, scheint es, dass Sie wirklich Anti-Muster verwenden. Ein Vorteil der Verwendung von Versprechen ist die Fehlerbehandlung. Für Ihren Fall würden Sie den folgenden Code nur brauchen:

var gitControl = Promise.promisifyAll(Main.gitControl); 
var promises = []; 
promises.push(gitControl.gitAddAsync(fileObj.filename, updateIndex)); 
return promises; 

Dies soll Ihren Anwendungsfall zu behandeln genug sein, um zu. Es ist viel klarer, und es hat auch den Vorteil, wirklich die Fehler richtig zu behandeln.

+0

Danke, ich werde ein "FIXME" setzen, um die aktuelle Methode durch die empfohlene zu ersetzen. Über den Weg des Q ... Soll ich 'var resolver = Promise.defer(), queue = neues Versprechen (Resolver);'? Es löst denselben Fehler aus. –

+0

@FezVrasta siehe das Beispiel [progress] (https://github.com/petkaantonov/bluebird/blob/master/API.md#progressdynamic-value---undefined), um die Verwendung von 'Promise.defer()' zu sehen . –

+0

Ich habe meine Frage aktualisiert, indem ich ein Code-Snippet hinzugefügt habe, ich kann Ihre vorgeschlagene Methode dort nicht implementieren, ich bekomme den gleichen Fehler ... Können Sie mir helfen? –

37

Florian hat eine gute Antwort geliefert Für die ursprüngliche Frage gibt es mehrere Möglichkeiten, eine Kette mit Bluebird zu starten.

Eine der einfachsten ruft Promise.resolve() auf nichts:

var queue = Promise.resolve(); //resolve a promise with nothing or cast a value 

oder

Promise.try(function(...){ 
    return ...//chain here 
}); 

So können Sie tun:

var queue = Promise.resolve() 
    promises = []; 
queue = queue.then(function() { 
    return Main.gitControl.gitAdd(fileObj.filename, updateIndex); 
}); 

// Here more promises are added to queue in the same way used above... 
promises.push(queue); 
return Promise.all(promises).then(function() { 
    // ... 
}); 

Obwohl ich persönlich würde etwas tun, wie :

//arr is your array of fileObj and updateIndex 

Promise.map(arr,function(f){ return Main.gitControl.gitAdd(f.filename,f.updateIndex). 
    then (function(result){ 
     //results here 
    }); 
+0

Wenn Sie möchten, dass jeder gitAdd auf den nächsten wartet, sollten Sie 'Promise.reduce' anstelle von' Promise.map' verwenden. –

+3

Warum ist 'Promise.resolve()' besser als 'Promise.cast()'? –

+3

@FlorianMargaine gute Frage, Promsie.resolve ist in der ES6-Spezifikation, als die API erstellt wurde Promise.cast und Promise.resolve waren beide in der ES6-Spezifikation und Bluebird, ich nehme an, dass '.cast' in Bluebird gelöscht wird 2.0. –

0

Ich stieß auf diese Methode, die eine Ressource im Internet abruft und den Inhalt zurückgibt, aber ich möchte, dass es Verbindungstimeouts verarbeitet und bis zu X-Zeiten mit Verzögerungen dazwischen wiederholt.

Als Bluebird.defer veraltet ist, habe ich dies, die diesen Trick:

const Promise = require('bluebird'); 

var fetch = function (options, promise) { 
    var resolve, reject; 
    if (promise) { 
     resolve = promise.resolve; 
     reject = promise.reject; 
     promise = promise.promise; 
    } else { 
     promise = new Promise(function() { 
      resolve = arguments[0]; 
      reject = arguments[1]; 
     }); 
    } 
    var retry = {promise: promise, resolve: resolve, reject: reject}; 

    // Your logic here that you want to retry 
    if (typeof options.x === 'undefined') { 
     reject(new Error('X not defined')); 
    } else if (options.x < 3) { 
     options.x++; 
     options.retryAttempt = (options.retryAttempt || 0) + 1; 
     console.log(`Retrying in 1 second attempt ${options.retryAttempt}...`); 
     setTimeout(() => { 
      fetch(options, retry) 
     }, 1000); 
    } else { 
     resolve(options.x); 
    } 

    return promise; 
} 

fetch({x:0}) 
    .then(res => { 
     console.log(res); 
    }) 
    .catch(err => { 
     throw err; 
    });