Javascript 理解promise.race()用法

Javascript 理解promise.race()用法,javascript,jquery,ajax,es6-promise,Javascript,Jquery,Ajax,Es6 Promise,据我所知,有两种选择: 好的,我知道promise.all()做什么。它并行运行promissions,。然后,如果两者都成功解析,则将为您提供值。以下是一个例子: Promise.all([ $.ajax({ url: 'test1.php' }), $.ajax({ url: 'test2.php' }) ]) .then(([res1, res2]) => { // Both requests resolved }) .catch(error => {

据我所知,有两种选择:

好的,我知道promise.all()做什么。它并行运行promissions,
。然后,如果两者都成功解析,则
将为您提供值。以下是一个例子:

Promise.all([
  $.ajax({ url: 'test1.php' }),
  $.ajax({ url: 'test2.php' })
])
.then(([res1, res2]) => {
  // Both requests resolved
})
.catch(error => {
  // Something went wrong
});
但是我不明白
承诺了什么。race()
到底应该做什么?换句话说,不使用它有什么区别?假设:

$.ajax({
    url: 'test1.php',
    async: true,
    success: function (data) {
        // This request resolved
    }
});

$.ajax({
    url: 'test2.php',
    async: true,
    success: function (data) {
        // This request resolved
    }
});
看到了吗?我没有使用过
promise.race()
,它的行为类似于
promise.race()
。无论如何,有没有简单明了的例子告诉我什么时候应该使用
promise.race()

正如您所看到的,
race()
将返回首先解析或拒绝的promise实例:

var p1=新承诺(函数(解析、拒绝){
setTimeout(解析,500,“一”);
});
var p2=新承诺(函数(解析、拒绝){
setTimeout(解析,100,'two');
});
Promise.race([p1,p2])。然后(函数(值){
console.log(值);/“两个”
//两者都可以解决问题,但p2更快

});下面是一个简单的示例,可以理解
promise.race()
的用法:

假设您需要从服务器获取一些数据,如果数据加载时间过长(比如15秒),您希望显示错误


您可以通过两个承诺调用promise.race(),第一个是ajax请求,第二个是简单的设置超时(()=>resolve(“ERROR”),15000)

这是构建超时系统的一部分,其中:

  • 请求/计算可能会被另一个通道取消
  • 稍后仍将使用它,但我们现在需要交互
  • 例如,第二个示例可能会“立即”显示微调器,但如果它足够快,仍然默认显示真实内容。试着运行下面的命令几次-注意至少有一些控制台消息“立即”出现。这通常可以附加在UI上执行操作

    需要注意的关键是,
    Promise.race
    的结果远不如副作用重要(不过,这是一种代码气味)

    //300毫秒感觉“瞬间”,闪烁不好
    函数getUserInfo(用户){
    返回新承诺((解决、拒绝)=>{
    //在1500时,它更真实,但900更适合测试
    setTimeout(()=>resolve(“用户数据”)、Math.floor(900*Math.random());
    });
    }
    函数showUserInfo(用户){
    返回getUserInfo()。然后(info=>{
    日志(“用户信息:”,信息);
    返回true;
    });
    }
    函数showSpinner(){
    console.log(“请稍候…”)
    }
    功能超时(延迟、结果){
    返回新承诺(解决=>{
    setTimeout(()=>解析(结果),延迟);
    });
    }
    Promise.race([showUserInfo(),超时(300)])。然后(显示=>{
    如果(!显示)showSpinner();
    
    });我已经将其用于请求批处理。为了长时间执行,我们不得不将成千上万条记录分批处理。我们可以并行进行,但不希望挂起的请求数量失控

    Race允许我们保持固定数量的并行承诺运行,并在完成时添加一个以替换

    const _ = require('lodash')
    
    async function batchRequests(options) {
        let query = { offset: 0, limit: options.limit };
    
        do {
            batch = await model.findAll(query);
            query.offset += options.limit;
    
            if (batch.length) {
                const promise = doLongRequestForBatch(batch).then(() => {
                    // Once complete, pop this promise from our array
                    // so that we know we can add another batch in its place
                    _.remove(promises, p => p === promise);
                });
                promises.push(promise);
    
                // Once we hit our concurrency limit, wait for at least one promise to
                // resolve before continuing to batch off requests
                if (promises.length >= options.concurrentBatches) {
                    await Promise.race(promises);
                }
            }
        } while (batch.length);
    
        // Wait for remaining batches to finish
        return Promise.all(promises);
    }
    
    batchRequests({ limit: 100, concurrentBatches: 5 });
    

    摘要:

    Promise.race
    是一个JS内置函数,它接受一组Promise(例如
    Array
    )作为参数。然后,当iterable中传递的承诺中的一个被解析或拒绝时,此函数异步返回一个承诺

    示例1:

    var promise1=新承诺((解决、拒绝)=>{
    setTimeout(()=>resolve('Promise-one'),500);
    });
    var promise2=新承诺((解决、拒绝)=>{
    setTimeout(()=>resolve('Promise-two'),100);
    });
    承诺。种族([promise1,promise2])。然后((值)=>{
    console.log(值);
    //双方都下定决心,但承诺2比承诺1快
    
    });
    让我们来看看下面的
    Promise.race
    的示例解决方法

    const race = (promises) => {
        return new Promise((resolve, reject) => {
            return promises.forEach(f => f.then(resolve).catch(reject));
        })
    };
    

    您可以看到
    race
    函数执行所有承诺,但谁先完成,谁将使用包装器
    Promise

    解决/拒绝您的网络呼叫,为什么不使用超时设置?@JaromandaX是对的。在您的示例中,在ajax请求中使用
    timeout
    会更好。无论如何,谢谢您,upvote然而,
    fetch
    方法调用仍在继续,但无论何时返回,输出都将被丢弃。超时应该会取消挂起的请求。与
    承诺.任何
    相比有什么区别吗?@Dominic区别在于
    承诺.种族
    会更快,原因如下:
    承诺.种族
    会在您提供的任何承诺解决后立即解决,无论它们是履行还是拒绝<代码>承诺。任何
    都会在您提供的任何承诺兑现或全部被拒绝后立即结算,在这种情况下,它会被AggregateError拒绝。因此,在“全部拒绝”场景中,
    Promise.any
    将变慢,因为它将等待所有承诺被拒绝。差别不大,但仍然是。很好的例子,@Iiridayn。不过,关于第一个问题,我很好奇为什么您选择将您的
    timeout
    视为一个异常,浪费执行
    setpinner()的
    catch
    块,而不是像
    var delayedSpinner=(ms)=>new Promise((resolve,reject)=>setTimeout(resolve,ms,'please wait…);Promise.race([showUserInfo(),delayedSpinner(300)])
    。这样,您仍然可以正确地处理来自
    showUserInfo
    的异常,而不是默默地删除它们,从而永远显示微调器。@JayAllen我不想在显示微调器之前取消超时或检查共享状态。我已经对它进行了更新,以解析一个布尔值(console.log返回的
    undefined
    为false),这样您就可以在生产代码中使用它,而修改的代码就更少了