等待异步执行,然后继续循环

时间:2018-08-02 04:12:48

标签: javascript node.js asynchronous promise async-await

我想在这里解决问题。在打印完成之前,我们需要打印5个星号*。

let arr = [1, 2, 3, 4, 5];

for (let i = 0; i < arr.length; i++) {
    delay();
    console.log('finished');
}

function delay() {
   setTimeout(() => {
        console.log('*');
    }, 1000)
}

我想解决此问题的一种方法是使用await关键字并将代码修改为如下所示

let arr = [1, 2, 3, 4, 5];

async function processArray() {
    for (let i = 0; i < arr.length; i++) {
      await delay();
      console.log('done');
    }
}

function delay() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(console.log('*'));
        }, 1000)
    });
}

可以通过哪些其他方式实现目标?我想最小化更改原始代码。我刚刚开始在节点中进行异步编程,想知道可能的方法。 同样,任何指向可用来学习和实施各种怪癖和变通办法的资源的指针都将很棒!

谢谢!

7 个答案:

答案 0 :(得分:1)

由于延迟函数是异步的,因此在for循环内调用它不会产生准确的结果。我认为您应该使用如下的递归逻辑。

let i = 0;
delay(i);

function delay(i) {
    if (i < 5) {
        setTimeout(() => {
            console.log('*');
            i++;
            delay(i);
        }, 1000)
    }
    else {
        console.log('finished');
    }
}

答案 1 :(得分:0)

这样对您有用吗?

let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
  setTimeout(() => {
    console.log('*')
  }, i * 1000)
}

答案 2 :(得分:0)

您在寻求其他可能的方法来解决此问题。另一种方法可能是这样:

let arr = [1, 2, 3, 4, 5];
let progress = 0;

function processArray() {
    for (let i = 0; i < arr.length; i++) {
        delay();    
    }  
}

function delay() {
   setTimeout(() => {
      console.log('*');
      progress++;

      if(progress === arg.length){
          console.log('finished');
      } 

   }, 1000)
}

答案 3 :(得分:0)

您还可以:

Number

答案 4 :(得分:0)

这是另一种方式:

function PA(parms) {
  this.id = parms.id;
  this.ai = undefined;
  if ("maxCount" in parms)
    this.maxCount = parms.maxCount;
  this.count = 0;
}
PA.objs = [];
PA.prototype.ms  = 1000;
PA.prototype.maxCount = 5;
PA.prototype.stop = function() {
      if (this.ai) {
        clearInterval(this.ai);
        this.ai = undefined;
      }
  };
PA.prototype.start = function() {
      if (this.ai) this.stop();
      this.ai = setInterval("PA.objs[" + id + "].rn()", this.ms);
  };
PA.prototype.rn = function() {
    console.log("*");
    if (this.count<this.maxCount) {
      this.count += 1;
    }
    else {
      console.log("done.");
      this.stop();
    }
  };

var id = 0;
PA.objs[id] = new PA({id: id});
PA.objs[id].start();

答案 5 :(得分:0)

使用计时器创建异步任务时,node.js的V8引擎将从堆栈中删除该任务,并等待计时器递减计数。因此,console.log("finished")是开始时仅留在函数堆栈中的唯一任务,也是其首先在屏幕上打印的原因。即使将计时器设置为0毫秒,也会产生相同的结果。

另一种解决方案如下。

let arr = [1, 2, 3, 4, 5];
var counter = 1;
for (let i = 0; i < arr.length; i++) {
    delay();
}

function delay() {
   setTimeout(() => {
        console.log('*');
        counter += 1
        if (counter === arr.length)
            print();
    }, 1000)
}

function print(){
    console.log('finished');
}

答案 6 :(得分:0)

解决问题的另一种方法是使用事件,如:

'use strict';
/* eslint-env node, es6 */

const EventEmitter = require('events');

/**
 * Count of running instances of the Event in delayedPrint.
 * @type {Number}
 */
let instances = 0;

/**
 * Prints message to console after delay milliseconds.
 *
 * @param  {String} message  - the message to print
 * @param  {Number} delay    - the number of milliseconds to delay printing
 */
const delayedPrint = (message, delay) => {
  const evt = new EventEmitter();

  message = (message || '').toString(); // assure message is a string
  delay = Number(delay) || 0; // assure delay is a number

  evt.on('start', () => { // uses setTimeout() to schedule an emit in the future
    instances++;
    setTimeout(() => {
      evt.emit('end');
    }, delay);
  });

  evt.on('end', () => { // what happens after delay milliseconds
    console.log(message);
    instances--;
    if (!instances) { // what happens after all running instances are complete.
      console.log('done');
    }
  });

  evt.emit('start'); // start delay
};

delayedPrint('It is now 10 seconds later!', 10 * 1000);
delayedPrint('It is now 5 seconds later!', 5 * 1000);
delayedPrint('It is now 1 second later!', 1 * 1000);