javascript 像 Q 一样定义空的 Bluebird 承诺
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22684643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Define empty Bluebird promise like in Q
提问by Fez Vrasta
With Q I can define a new promise with:
使用 QI 可以定义一个新的承诺:
var queue = q();
But with Bluebird if I do:
但是如果我这样做,蓝鸟:
var queue = new Promise();
I get:
我得到:
TypeError: the promise constructor requires a resolver function
How can I get the same result that I had with Q?
我怎样才能得到与 Q 相同的结果?
This is a snippet of my 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 () {
// ...
});
采纳答案by Florian Margaine
var resolver = Promise.defer();
setTimeout(function() {
resolver.resolve(something); // Resolve the value
}, 5000);
return resolver.promise;
This line is quite often used in the documentation.
这一行在文档中经常使用。
Be aware that this is usually an anti-pattern to use that. But if you know what you're doing, Promise.defer()
is a way to get the resolver that is similar Q's way.
请注意,这通常是使用它的反模式。但是,如果您知道自己在做什么,Promise.defer()
则是一种获得类似于 Q 方式的解析器的方法。
It is, however, discouraged to use this method. Bluebird has even deprecated it.
但是,不鼓励使用这种方法。Bluebird 甚至弃用了它。
Instead, you should use this way:
相反,您应该使用这种方式:
return new Promise(function(resolve, reject) {
// Your code
});
See the relevant documentation bits: Promise.defer()and new Promise().
请参阅相关文档位:Promise.defer()和new Promise()。
After the update of your question, here is your issue: you're reusing the same promise to resolve several values. A promise can only be resolved once.It means you have to use Promise.defer()
as many times as you have promises.
更新您的问题后,这是您的问题:您正在重用相同的承诺来解决多个值。一个承诺只能被解决一次。这意味着您必须使用Promise.defer()
与承诺一样多的次数。
That said, after seeing more of your code, it seems you're really using anti-patterns. One advantage of using promises is error handling. For your case, you'd just need the following code:
也就是说,在看到更多代码之后,您似乎真的在使用反模式。使用 Promise 的优势之一是错误处理。对于您的情况,您只需要以下代码:
var gitControl = Promise.promisifyAll(Main.gitControl);
var promises = [];
promises.push(gitControl.gitAddAsync(fileObj.filename, updateIndex));
return promises;
This should be enough to handle your use case.It is a lot clearer, and it also has the advantage of reallyhandling the errors correctly.
这应该足以处理您的用例。清晰了很多,而且还有真正正确处理错误的优点。
回答by Benjamin Gruenbaum
Florian provided a good answer For the sake of your original question, there are several ways to start a chain with Bluebird.
Florian 提供了一个很好的答案 对于您最初的问题,有几种方法可以使用 Bluebird 启动链。
One of the simplest is calling Promise.resolve()
on nothing:
最简单的方法之一是Promise.resolve()
什么都不调用:
var queue = Promise.resolve(); //resolve a promise with nothing or cast a value
or
或者
Promise.try(function(...){
return ...//chain here
});
So you can do:
所以你可以这样做:
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 () {
// ...
});
Although, personally I'd do something like:
虽然,我个人会做这样的事情:
//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
});
回答by Kus
I came across this as I had a method which fetches a resource on the internet and returns the content, but I want it to handle connection timeouts and retrying up to X times with delays between.
我遇到了这个问题,因为我有一个方法可以在 Internet 上获取资源并返回内容,但我希望它处理连接超时并重试 X 次,中间有延迟。
As Bluebird.defer
is deprecated, I used this which does this trick:
由于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;
});
回答by Sam Berry
I find a pattern like this useful for any kind of integration testing.
我发现这样的模式对任何类型的集成测试都很有用。
const responseResolver;
const response = new Promise(resolve => {
responseResolver = resolve;
}).then(data => {
console.log("data: ", data);
return data;
});
// mock some method that returns a promise (e.g. waits for a response)
service.getIceCreams = () => response;
// do some assertions while the response is pending
responseResolver("cookie dough"); // will trigger .then: "data: cookie dough"
// do some assertions now that the response is completed