36

使用 QI 可以定义一个新的承诺:

var queue = q();

但是如果我这样做的话,使用蓝鸟:

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 () {
   // ...
});
4

4 回答 4

37

Florian 提供了一个很好的答案为了您最初的问题,有几种方法可以使用 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
    });
于 2014-03-27T14:06:03.680 回答
23
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()new Promise()


更新您的问题后,这是您的问题:您正在重用相同的承诺来解决多个值。一个承诺只能解决一次。这意味着您必须使用Promise.defer()与承诺一样多的次数。

也就是说,在查看了更多代码之后,您似乎真的在使用反模式。使用 Promise 的优点之一是错误处理。对于您的情况,您只需要以下代码:

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

这应该足以处理您的用例。它更清晰,并且它还具有真正正确处理错误的优点。

于 2014-03-27T10:32:09.407 回答
0

我遇到了这个问题,因为我有一个方法可以在 Internet 上获取资源并返回内容,但我希望它能够处理连接超时并重试多达 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;
    });
于 2017-02-14T01:43:32.073 回答
0

我发现这样的模式对任何类型的集成测试都很有用。

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
于 2018-05-02T11:20:53.927 回答