在promise.all中为每个promise设置超时 [英] Setting a timeout for each promise within a promise.all

查看:185
本文介绍了在promise.all中为每个promise设置超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我能够成功执行Promise.all,并优雅地处理解析和拒绝。但是,有些承诺会在几毫秒内完成,有些可能/可能需要一段时间。

I am able to successfully perform a Promise.all, and gracefully handle resolves and rejects. However, some promises complete within a few milliseconds, some can/could take a while.

我希望能够为Promise.all中的每个承诺设置超时。 ,所以它可以尝试最多花费5秒。

I want to be able to set a timeout for each promise within the Promise.all, so it can attempt to take a maximum of say 5seconds.

getData() {
    var that = this;
    var tableUrls = ['http://table-one.com','http://table-two.com'];
    var spoonUrls = ['http://spoon-one.com','http://spoon-two.com'];

    var tablePromises = that.createPromise(tableUrls);
    var spoonPromises = that.createPromise(spoonUrls);
    var responses = {};

    var getTableData = () => {
        var promise = new Promise((resolve, reject) => {
            Promise.all(tablePromises.map(that.rejectResolveHandle))
                .then((results) => {
                    responses.tables = results.filter(x => x.status === 'resolved');
                    resolve(responses);
                });
        });
        return promise;
    };

    var getSpoonData = () => {
        var promise = new Promise((resolve, reject) => {
            Promise.all(spoonPromises.map(that.rejectResolveHandle))
                .then((results) => {
                    responses.tables = results.filter(x => x.status === 'resolved');
                    resolve(responses);
                });
        });
        return promise;
    };


    return getTableData()
        .then(getSpoonData);
}

rejectResolveHandle() {
    return promise.then(function(v) {
        return {v:v, status: "resolved"};
    }, function(e) {
        return {e:e, status: "rejected"};
    });
}

createPromise(links) {
    var promises = [];
    angular.forEach(links, function (link) {
        var promise = that._$http({
            method: 'GET',
            url: link + '/my/end/point',
            responseType: 'json'
        });
        promises.push(promise);
    });

    return promises;
}

我试过在 createPromise()中添加超时,但这似乎不起作用。将超时设置为300毫秒,一些请求持续4 +秒:

I have tried adding a timeout to createPromise(), however this does not seem to work. Setting a timeout to 300ms, some requests continue for 4+seconds:

createPromise(links) {
    var promises = [];
    angular.forEach(links, function (link) {
        var promise = that._$http({
            method: 'GET',
            url: link + '/my/end/point',
            responseType: 'json'
        });

        promise = new Promise((resolve) => {
            setTimeout(() => {
                resolve(promise);
            }, 300);
        });

        promises.push(promise);
    });

    return promises;
}

如果能让事情变得更轻松,我可以访问Bluebird吗?

I have access to Bluebird if it will makes things easier?

推荐答案

这是一个创建 Promise.raceAll()函数的方案比如 Promise.all() Promise.race()的组合,其中所有承诺都有超时时间和如果promise在该时间之前没有解决,那么它将被短路以解决传入的值。这基本上将每个承诺放入带有计时器的 Promise.race()。如果计时器获胜,则使用默认值解析承诺。如果原始承诺获胜,则通过实际承诺结果解决。我们使用 Promise.race()来解决第一个完成(超时或原始承诺)。这是 Promise.race()的经典用法(实际上是我用过它的唯一实际用途)。

Here's a scheme that creates a Promise.raceAll() function that works kind of like a combination of Promise.all() and Promise.race() where the promises all have a timeout time and value so that if the promise doesn't resolve before that time, it will be short circuited to resolve with the passed in value. This essentially puts each promise into a Promise.race() with a timer. If the timer wins, the promise is resolved with the default value. If the original promise wins, it's resolved with the actual promise result. We use Promise.race() to resolve with the first one to finish (the timeout or the original promise). This is a classic use for Promise.race() (in fact the only practical use I've ever really used it for).

一个典型的例子就是在接下来的15秒内获得所有结果。任何花费超过15秒的结果,只需为它们返回 null ,不要等待它们。以下是使这个概念有效的代码:

A classic example would be to get me all the results you can in the next 15 seconds. Any results that take longer than 15 seconds, just return null for them and don't wait for them. Here's the code to make this concept work:

Promise.delay = function(t, val) {
    return new Promise(resolve => {
        setTimeout(resolve.bind(null, val), t);
    });
}

Promise.raceAll = function(promises, timeoutTime, timeoutVal) {
    return Promise.all(promises.map(p => {
        return Promise.race([p, Promise.delay(timeoutTime, timeoutVal)])
    }));
}

所以,你使用 Promise.raceAll()喜欢 Promise.all(),你传递一个promises数组,但你也传递了一个 timeoutTime timeoutVal timeoutTime 是超时承诺之前等待的时间。 timeoutVal 是什么放在结果数组中的任何超时的承诺(通常它会像 null 你可以很容易地认出是非真实的结果。)

So, you use Promise.raceAll() like Promise.all() in that you pass it an array of promises, but you also pass it a timeoutTime and a timeoutVal. The timeoutTime is the how long to wait before timing out the promises. The timeoutVal is what to put in the results array for any promise that timed out (often it will be something like null that you can easily recognize as a non-real result).

我不确定我到底在做什么在您的特定代码中,但这是使用上述代码的链接代码:

I'm not sure I entirely what you are doing in your specific code, but here's your links code using the above:

Promise.raceAll(links.map(link => {
    return that._$http({
        method: 'GET',
        url: link + '/my/end/point',
        responseType: 'json'
    });
}), 5000, null).then(results => {
    // process results here
    // any timed out values will be null
    // you can filter out the timed out results
    let final = results.filter(item => !!item);
}).catch(err => {
    // process any errors here
});

或者,如果你想确保 Promise.raceAll()获取所有结果,即使某些承诺拒绝,您也可以为每个承诺添加 .catch()处理程序:

Or, if you want to make sure Promise.raceAll() gets all results, even if some promises reject, you can add a .catch() handler to each promise:

Promise.raceAll(links.map(link => {
    return that._$http({
        method: 'GET',
        url: link + '/my/end/point',
        responseType: 'json'
    }).catch(err => {
        // don't let Promise.all() see a reject so it gets all results
        return null;
    });
}), 5000, null).then(results => {
    // process results here
    // any timed out values will be null
    // you can filter out the timed out or rejected results
    let final = results.filter(item => !!item);
}).catch(err => {
    // process any errors here
});

这篇关于在promise.all中为每个promise设置超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆