Определите пустое обещание Bluebird, как в Q
С Q я могу определить новое обещание с помощью:
var queue = q();
Но с Bluebird, если я это сделаю:
var queue = new Promise();
Я получаю:
TypeError: the promise constructor requires a resolver function
Как я могу получить тот же результат, что и у Q?
Это фрагмент кода:
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
var resolver = Promise.defer();
setTimeout(function() {
resolver.resolve(something); // Resolve the value
}, 5000);
return resolver.promise;
Эта строка довольно часто используется в документации .
Имейте в виду, что для этого обычно используется анти-шаблон. Но если вы знаете, что вы делаете, Promise.defer()
- это способ получить резольвер, похожий на Q.
Однако этот метод не рекомендуется использовать. Bluebird даже устарел.
Вместо этого вы должны использовать этот способ:
return new Promise(function(resolve, reject) {
// Your code
});
См. соответствующие биты документации: Promise.defer() и новый Promise().
После обновления вашего вопроса, вот ваша проблема: вы повторно используете одно и то же обещание для решения нескольких значений. Обещание может быть разрешено только один раз. Это означает, что вы должны использовать Promise.defer()
столько раз, сколько у вас есть promises.
Тем не менее, увидев больше вашего кода, кажется, что вы действительно используете анти-шаблоны. Одним из преимуществ использования promises является обработка ошибок. Для вашего случая вам просто нужен следующий код:
var gitControl = Promise.promisifyAll(Main.gitControl);
var promises = [];
promises.push(gitControl.gitAddAsync(fileObj.filename, updateIndex));
return promises;
Этого должно быть достаточно, чтобы обрабатывать ваш прецедент. Это намного понятнее, и это также имеет преимущество действительно корректно обрабатывать ошибки.
Ответ 2
Флориан предоставил хороший ответ. Во имя вашего первоначального вопроса есть несколько способов начать цепочку с Bluebird.
Один из простейших вызывает Promise.resolve()
ничего:
var queue = Promise.resolve(); //resolve a promise with nothing or cast a value
или
Promise.try(function(...){
return ...//chain here
});
Итак, вы можете сделать:
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 () {
// ...
});
Хотя, лично я бы сделал что-то вроде:
//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
});
Ответ 3
Я столкнулся с этим, поскольку у меня был метод, который извлекает ресурс в Интернете и возвращает содержимое, но я хочу, чтобы он обрабатывал таймауты соединений и повторял до X раз с задержками между ними.
Поскольку Bluebird.defer
устарел, я использовал это, что делает этот трюк:
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;
});