等待不是等待api发布完成,只是同时发生

时间:2020-05-14 18:52:38

标签: javascript async-await

我有一个我似乎无法弄清的问题。我需要只有在循环中一个接一个地完成时才能进行此await调用,但是似乎它只是在同一时间快速调用了两次,这无法使api帖子正常工作。

我尝试使用async,await,但是await似乎不喜欢它处于两个循环中。 有谁有更好的解决方案?

async pushToCreate() {
    const toCreate = this.json.toCreate

    let counter = 0

    // toCreate Sample = { en: [{}, {}] }, { fr: [{}, {}] }

    Object.keys(toCreate).forEach((item) => {
        toCreate[item].forEach((el) => {
            const lang = item
            const dataContent = el

            await this.wp.products().param('lang', lang).create({
                title: dataContent.dgn,
                fields:  dataContent,
                status: 'publish'
            }).then(function( response ) {
                counter++
            }).catch(function(err) {
                console.log('error in create', err)
            })

            console.log('await finished')
        })
    })

    // should console log when above is finished
    console.log('END')
}

2 个答案:

答案 0 :(得分:1)

  1. 如果您要等待以兑现承诺, forEach 将无济于事。要使其正常工作,您应该使用:
    • for / for..in / for..of 循环用于顺序处理,每个 Promise 等待 strong>在每次迭代中都能实现
    • 地图进行并行处理,该处理将返回一组承诺,之后您可以等待以使它们通过 Promise.all()
  2. 如果您使用 async / await ,那么使用 try / catch 而不是 then / catch 链接
  3. 会更清楚

如果需要顺序处理,请尝试以下方法:

...

  let lang;
  let dataContent;

  for (const item in toCreate) {
    lang = item;

    for (let i = 0; i < toCreate[lang].length; i++) {
      dataContent = toCreate[lang][i];

      try {
        await this.wp.products().param('lang', lang).create({
          title: dataContent.dgn,
          fields: dataContent,
          status: 'publish',
        });

        counter++;
      } catch (err) {
        console.log('error in create', err);
      }

      console.log('await finished');
    }
  }

...

或者如果您需要并行处理,请执行以下操作:

...

  let lang;
  let dataContent;

  await Promise.all(
    Object.keys(toCreate).map(async item => {
      lang = item;

      await Promise.all(
        toCreate[lang].map(async el => {
          dataContent = el;

          try {
            await this.wp.products().param('lang', lang).create({
              title: dataContent.dgn,
              fields: dataContent,
              status: 'publish',
            });

            counter++;
          } catch (err) {
            console.log('error in create', err);
          }

          console.log('await finished');
        }),
      );
    }),
  );

...

以下是使用 async / await Using async/await with a forEach loop 顺序和并行异步呼叫处理的很好的解释: >

答案 1 :(得分:0)

我相信您的代码存在一些问题。

第一个是await仅在函数返回promise时起作用。返回promise的函数最初将返回一个值,该值指示promise尚未完成。如果您在等待右侧的功能没有返回承诺,它将不会等待。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

第二个是您还使用了.then()方法,当实现诺言时会触发它的回调参数。我认为您不能同时使用await和.then()。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

如果您希望使用与.then().catch()模式类似的格式,则可以在try / catch块中使用async / await。

async function f() {

  try {
    let response = await fetch('/example');
    let user = await response.json();
  } catch(err) {
    // catches errors both in fetch and response.json
    alert(err);
  }
}

https://javascript.info/async-await