了解promise.race()用法

据我所知, promise有两种选择:

  • promise.all()

  • promise.race()

好的,我知道promise.all()作用。 它并行运行promises,然后.then为两个值提供成功解析的值。 这是一个例子:

 Promise.all([ $.ajax({ url: 'test1.php' }), $.ajax({ url: 'test2.php' }) ]) .then(([res1, res2]) => { // Both requests resolved }) .catch(error => { // Something went wrong }); 

但是我不明白promise.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 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, 'one'); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'two'); }); Promise.race([p1, p2]).then(function(value) { console.log(value); // "two" // Both resolve, but p2 is faster }); 

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

  1. 请求/计算可以被另一个通道取消
  2. 它仍将在以后使用,但我们现在需要一个互动。

对于第二个例子,人们可能会“立即”显示一个微调器,而如果它足够快,则仍然默认显示真实内容。 尝试运行以下几次 – 注意至少有一些控制台消息“立即”出现。 通常可以附加此操作以在UI上执行操作。

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

 // 300 ms _feels_ "instant", and flickers are bad function getUserInfo(user) { return new Promise((resolve, reject) => { // had it at 1500 to be more true-to-life, but 900 is better for testing setTimeout(() => resolve("user data!"), Math.floor(900*Math.random())); }); } function showUserInfo(user) { return getUserInfo().then(info => { console.log("user info:", info); return true; }); } function showSpinner() { console.log("please wait...") } function timeout(delay, result) { return new Promise(resolve => { setTimeout(() => resolve(result), delay); }); } Promise.race([showUserInfo(), timeout(300)]).then(displayed => { if (!displayed) showSpinner(); }); 

这是一个简单的例子来理解promise.race()的用法:

想象一下,您需要从服务器获取一些数据,如果数据加载时间太长(例如15秒),则需要显示错误。

你可以使用两个promise调用promise.race(),第一个是你的ajax请求,第二个是简单的setTimeout(() => resolve("ERROR"), 15000)

我用它来请求批处理。 我们不得不将成千上万条记录分批批量处理,以便长时间执行。 我们可以并行完成,但不希望未决请求的数量失控。

 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内置函数,它接受一个可迭代的Promises(例如Array )作为参数。 一旦在iterable中传递的Promise中的一个被解析或被拒绝,该函数就会返回一个Promise。

例1:

 var promise1 = new Promise((resolve, reject) => { setTimeout(() => resolve('Promise-one'), 500); }); var promise2 = new Promise((resolve, reject) => { setTimeout(() => resolve('Promise-two'), 1000); }); Promise.race([promise1, promise2]).then((value) => { console.log(value); // Both resolve, but promise2 is faster than promise 1 }); 

Promise.race帮助您解决或拒绝第一个资源。

使用Node的一个真实示例(以避免浏览器中的CORS问题)

你应该在脚本下面运行多次

 const fetch = require('node-fetch'); const mirrors = ['astuteinternet', 'ayera', 'cfhcable', 'cytranet', 'datapacket', 'excellmedia', 'freefr', 'gigenet', 'iweb', 'jaist', 'kent', 'liquidtelecom', 'managedway', 'nchc', 'netcologne', 'netix', 'newcontinuum', 'phoenixnap', 'pilotfiber', 'razaoinfo', 'superb-dca2', 'superb-sea2', 'svwh', 'tenet', 'ufpr', 'versaweb']; const url = 'https://sourceforge.net/projects/filezilla/files/FileZilla_Client/3.31.0/FileZilla_3.31.0_win64-setup.exe/download'; // Find the fastest Sourceforge mirror manually // The usual use case would for Promise.race would be // when calling images from multiple servers // (imagine different AWS S3 storage) to get the fastest one var p = Promise.race( mirrors.map((mirror, index) => { return fetch(`${url}?use_mirror=${mirror}`); }) ); p.then(response => console.log(response.url));