Skip to content Skip to sidebar Skip to footer

Typescript - Settimeout Custom Time From Variable That Is Dynamic In For Loop

So I have this function that has a timeout that changes every 3s: setActiveImage(promotions) { for (let i = 0; i <= promotions.length - 1; i++) { setTimeout(()=> {

Solution 1:

Here is one of the possible solutions with the async function and setTimeout().

With async function, we make sure that the next slide is not executed before the first one is.

The thing that you should watch out with the setTimeout is that the timer will execute the given function AFTER the time expires.

So the working example should be something like this:

activeImage: string = 'https://pngimage.net/wp-content/uploads/2018/06/start-png-.png';

  promotions = [
    {
      time: 6,
      pic: 'https://pngimage.net/wp-content/uploads/2018/06/1-an-png-1.png'
    },
    {
      time: 3,
      pic: 'https://upload.wikimedia.org/wikipedia/commons/1/10/MRT_Singapore_Destination_2.png'
    },
    {
      time: 4,
      pic: 'https://upload.wikimedia.org/wikipedia/commons/a/aa/L%C3%ADnea_3_CAMETRO.png'
    }
  ];

  ngOnInit() {
      this.setActiveImage();
  }

  setActiveImage() {
    let _this = this;
    countDown();

    functionprinter(i) {

      returnnewPromise(resolve => {
        _this.activeImage = _this.promotions[i].pic;
        setTimeout(function () {
          resolve(true);
        }, _this.promotions[i].time * 1000);
      });
    }

    asyncfunctioncountDown() {
      for (var i = _this.promotions.length -1; i >= 0; i--) {
        awaitprinter(i);
      }
    }

  }

Live demo: https://stackblitz.com/edit/angular-qwtgm2

Solution 2:

I see two mistakes:

  1. You count i from 0. The result is that the first value (6 seconds) becomes 0 when you calculate timeout value so first function is executed almost immediately. Then the second value (3 seconds) is used for showing the second picture and is multiple by i which is 1 at that point (so you see the first one lasting 3 seconds). The third picture follows the same logic.

  2. You call all setTimeouts at the same time using i as some sort of separator. To achieve what you need you should call setTimeout for picture n + 1 after the setTimeout for picture n ends.

Solution 3:

per this answer Is setTimeout a good solution to do async functions with javascript?

setTimeout(function(){...}, 0) simply queues the code to run once the current call stack is finished executing.

so what's happens is the for loop finishes with promotions[i].time = 4 and the setTimeout piece of code runs with that value (at least this is what I see in your code in StackBlitz)...

Solution 4:

When working within an Angular context, I'd recommend to embrace to power of RxJs.

const MOCKED_DATA = [
  {
    time: "6",
    pic: "https://pngimage.net/wp-content/uploads/2018/06/1-an-png-1.png"
  },
  {
    time: "3",
    pic:
      "https://upload.wikimedia.org/wikipedia/commons/1/10/MRT_Singapore_Destination_2.png"
  },
  {
    time: "4",
    pic:
      "https://upload.wikimedia.org/wikipedia/commons/a/aa/L%C3%ADnea_3_CAMETRO.png"
  }
];

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  promotions$ = from(MOCKED_DATA).pipe(
    map(promotion => of(promotion.pic).pipe(delay(1000 * +promotion.time))),
    mergeAll(),
    startWith("https://pngimage.net/wp-content/uploads/2018/06/start-png-.png")
  );
}

and then in your template:

<img [src]="promotions$ | async" alt="Responsive image of item">

Live demo: https://stackblitz.com/edit/angular-xjcrgd?file=src/app/app.component.ts

Edit: I'm not sure whether the time is relative or not in your question but after reading it again I think it is. If that's the case, then you could build a remap function to have an absolute time like that:

const remapToAbsoluteTime = (data: ServerContent[]): LocalContent[] =>
  data.reduce((acc, x) => {
    if (!acc.length) {
      acc.push({
        ...x,
        time: +x.time
      });
    } else {
      acc.push({
        ...x,
        time: acc[acc.length - 1].time + +x.time
      });
    }

    return acc;
  }, []);

Then you'd have the photos ordered 1, 2, 3.

Live demo: https://stackblitz.com/edit/angular-6c4pqt?file=src/app/app.component.ts

Post a Comment for "Typescript - Settimeout Custom Time From Variable That Is Dynamic In For Loop"