如何在Promise.all()中使用async-await?

时间:2019-02-09 20:04:09

标签: javascript async-await

此刻,我正在使用下面的代码使用异步等待来获取多个Promises的结果:

let matchday = await createMatchday(2018, 21, [/*9 matches of matchday*/]);
//Further calculations

async function createMatchday(seasonNr, matchdayNr, matches) {
  let md = new Matchday(seasonNr, matchdayNr, matches);
  await md.getStandings(seasonNr, matchdayNr);
  return md;
}

class Matchday {
  constructor(seasonNr, matchdayNr, matches) {
    this.seasonNr = seasonNr;
    this.matchdayNr = matchdayNr;
    this.matches = matches;
  }

  async getStandings(seasonNr, matchdayNr) {
    let promiseArr = [];
    promiseArr.push(makeHttpRequestTo(`http://externService.com/standings?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`);
    promiseArr.push(makeHttpRequestTo(`http://externService.com/homestandings?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`));
    promiseArr.push(makeHttpRequestTo(`http://externService.com/awaystandings?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`));
    promiseArr.push(makeHttpRequestTo(`http://externService.com/formstandings?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`));

    let resulArr = await Promise.all(promiseArr);
    this.standings = resultArr[0];
    this.homeStandings = resultArr[1];
    this.awayStandings = resultArr[2];
    this.formStandings = resultArr[3];
  }
}

function makeHttpRequest(url) {
  return new Promise((resolve, reject) => {
    //AJAX httpRequest to url
    resolve(httpRequest.responseText);
  }
}

这实际上是读取多个promise的值的最佳方法,其中promise.all()不需要彼此等待,而是可以同时工作,或者是否有更好的方法使同时出现几个httpRequest,因为这看起来很重复吗?

4 个答案:

答案 0 :(得分:2)

您的所有URL都遵循相同的模式,因此您可以通过map对URL ['', 'home', 'away', 'form']的数组解析来极大地减少代码。然后,通过map makeHttpRequestTo到Promises的URL,然后可以将等待的结果分解为this.属性:

async getStandings(seasonNr, matchdayNr) {
  const urls = ['', 'home', 'away', 'form']
    .map(str => `http://externService.com/${str}standings?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`);
  const promiseArr = urls.map(makeHttpRequestTo);
  [
    this.standings,
    this.homeStandings,
    this.awayStandings,
    this.formStandings
  ] = await Promise.all(promiseArr);
}

要分别填充每个属性,而不是等待所有响应返回:

async getStandings(seasonNr, matchdayNr) {
  ['', 'home', 'away', 'form']
    .forEach((str) => {
      const url = `http://externService.com/${str}standings?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`;
      makeHttpRequestTo(url)
        .then((resp) => {
          this[str + 'Standings'] = resp;
        });
    });
}

答案 1 :(得分:0)

要回答,不,您不应阻止彼此不依赖的其他XHR或任何I / O请求。我会这样写你的函数的;

const getFavourites = async () => {
  try {
    const result = await Promise.resolve("Pizza");
    console.log("Favourite food: " + result);
  } catch (error) {
    console.log('error getting food');
  }
  try {
    const result = await Promise.resolve("Monkey");
    console.log("Favourite animal: " + result);
  } catch (error) {
    console.log('error getting animal');
  }
  try {
    const result = await Promise.resolve("Green");
    console.log("Favourite color: " + result);
  } catch (error) {
    console.log('error getting color');
  }
  try {
    const result = await Promise.resolve("Water");
    console.log("Favourite liquid: " + result);
  } catch (error) {
    console.log('error getting liquid');
  }
}

getFavourites();

这样,每个异步函数都会被立即调用,并且没有异步动作会阻止其他动作。

答案 2 :(得分:0)

如果您不希望在继续执行流程之前等待所有请求完成,则可以使该类的属性成为承诺:

class Matchday {
  constructor(seasonNr, matchdayNr, matches) {
    this.seasonNr = seasonNr;
    this.matchdayNr = matchdayNr;
    this.matches = matches;
    ['standings', 'homeStandings', 'awayStandings', 'formStandings'].forEach(propertyName => {
      let url = `http://externService.com/${propertyName.toLowerCase()}`
        + `?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`
      this[propertyName] = makeHttpRequestTo(url)
    });
  }
}

使用以下代码段进行测试

class Matchday {
  constructor(seasonNr, matchdayNr, matches) {
    this.seasonNr = seasonNr;
    this.matchdayNr = matchdayNr;
    this.matches = matches;
    ['standings', 'homeStandings', 'awayStandings', 'formStandings'].forEach(propertyName => {
      let url = `http://externService.com/${propertyName.toLowerCase()}`
        + `?seasonNr=${seasonNr}&matchdayNr=${matchdayNr}`
      this[propertyName] = makeHttpRequestTo(url)
    });
  }
}

/**************************************
 * Test harness
 **************************************/
 
function makeHttpRequestTo(url) {
  // Fake an AJAX httpRequest to url
  const requested_resource = url.match('^.*\/\/.*\/([^?]*)')[1];
  const fake_response_data = 'data for ' + url.match('^.*\/\/.*\/(.*)$')[1];
  let delay = 0;
  let response = '';
  switch (requested_resource) {
    // To make it interesting, let's give the 'standings' resource 
    // a much faster response time
    case 'standings':
      delay = 250;
      break;
    case 'homestandings':
      delay = 2000;
      break;
    case 'awaystandings':
      delay = 3000;
      break;
    case 'formstandings':
      delay = 4000; // <== Longest request is 4 seconds
      break;
    default:
      throw (util.format('Unexpected requested_resource: %s', requested_resource));
  }
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(fake_response_data), delay);
  });
}

async function testAccessingAllProperties() {
  const testId = "Test accessing all properties";
  console.log('\n%s', testId);
  console.time(testId)
  let md = new Matchday(2018, 21, []);
  console.log(await md.standings);
  console.log(await md.homeStandings);
  console.log(await md.awayStandings);
  console.log(await md.formStandings);
  console.timeEnd(testId)
}

async function testAccessingOnlyOneProperty() {
  const testId = `Test accessing only one property`;
  console.log('\n%s', testId);
  console.time(testId)
  let md = new Matchday(2018, 21, []);
  console.log(await md.standings);
  console.timeEnd(testId)
}

async function all_tests() {
  await testAccessingAllProperties();
  await testAccessingOnlyOneProperty();
}

all_tests();

结论

上面的代码片段显示执行时间不受未访问的属性的影响。而且访问所有属性的执行时间并不比使用promise.all差。

访问这些属性时,您只需要记住使用await

答案 3 :(得分:-1)

要创建Promise,您需要调用新的Promise((resolve,reject)=> {return“ Pizza”;})

您做对了

如果您愿意,可以使用数组(及其函数,如map等来缩短代码,但不会提高其性能