function abc(elm){
this.$elm = document.querySelector(elm)
}
abc.prototype.addClass = function (str){
this.$elm.classList.add(str)
return this
}
abc.prototype.removeClass = function (str){
this.$elm.classList.remove(str)
return this
}
abc.prototype.delay = function (timer){
let self = this
setTimeout(()=>{
return self
},timer)
return this
}
function $(str){
return new abc(str);
}
let x = $('#test').delay(5000).delay(1000).addClass('red');
console.log($('#test'));
I want to add red class after 6 secs.I tried like using setTimeout but not work.could you please suggest the better way ?
I want to write a delay function which delay for sometime before proceeding/executing next code.
4 Answers 4
You can make a very simple queue of tasks to be executed based off promises. Since the promise execution already uses a task queue, you just need to keep a single promise and any time you get a new thing to add, you chain it via .then() and keep the latest promise. That way if you add three tasks T1 -> T2 -> T3, they would resolve in the order they were added. If you add a task that just adds a simple delay between them like T1 -> wait 6 seconds -> T2 -> wait 5 seconds -> T3 then that will run also space out the executions.
This is a sample implementation to illustrate the idea that utilises thunks (functions that take no parameters) as task to delay and execute later.
function abc(elm){
this.$elm = document.querySelector(elm)
this.queue = Promise.resolve();
}
/**
* Uniform way of adding a task for later execution
* @param {Function} task - a thunk to be executed later
* @param {number} [delay=0] time in milliseconds to wait after last task finished before executing this on
*/
abc.prototype.addTask = function(task, delay = 0) {
const waitFor = () => new Promise( res => setTimeout(res, delay) );
this.queue = this.queue
.then(waitFor)
.then(task)
}
abc.prototype.addClass = function (str){
this.addTask(() => this.$elm.classList.add(str));
return this
}
abc.prototype.removeClass = function (str){
this.addTask(() => this.$elm.classList.remove(str));
return this
}
abc.prototype.delay = function (timer){
// add an empty function as a task. If needed this can also do logging or other internal logic
this.addTask(() => {}, timer);
return this
}
function $(str){
return new abc(str);
}
//usage
let x = $('#test').delay(5000).delay(1000).addClass('red');
x.delay(1000)
.delay(1000)
.delay(1000)
.delay(1000)
.delay(1000) //5 seconds
.removeClass('red');
.red {
background-color: red;
color: white;
}
<p id="test">
Bacon ipsum dolor amet hamburger t-bone pork, pastrami sirloin swine corned beef tenderloin frankfurter tail ball tip meatball pork belly spare ribs prosciutto. Bresaola turkey buffalo jowl t-bone biltong burgdoggen cow capicola meatball pastrami boudin alcatra. Bresaola chicken bacon cow, frankfurter meatball hamburger jerky. Shankle capicola chicken leberkas turkey. Ball tip bacon doner kielbasa jerky. Salami picanha chicken bacon, turducken buffalo chislic andouille porchetta tongue shankle prosciutto t-bone. Beef andouille cow pork chop alcatra, turducken ribeye sirloin tail boudin strip steak doner.
</p>
Comments
You need promise.
abc.prototype.delay = function (timer) {
return new Promise((resolve) => {
let self = this
setTimeout(() => {
return resolve(self)
}, timer)
return resolve(this);
})
}
let x = $('#test').delay(5000);
Please find below example.
function abc(elm) {
this.$elm = document.querySelector(elm)
}
abc.prototype.addClass = function(str) {
this.$elm.classList.add(str)
return this
}
abc.prototype.removeClass = function(str) {
this.$elm.classList.remove(str)
return this
}
abc.prototype.delay = function(timer) {
return new Promise((resolve) => {
let self = this
setTimeout(() => {
return resolve(self)
}, timer)
})
}
function $(str) {
return new abc(str);
}
async function hello() {
let x = $('body')
await x.delay(5000);
x.addClass('red');
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
.red {
background: red;
}
</style>
<body>
<button onclick="hello()">Click here...</button>
</body>
</html>
1 Comment
delay/addClass like in their sample code.You just can't do that throught SYNCRONOUS way. That would stop the whole app for that time out
The best way is using ASYNCRONOUS and callbacks
abc.prototype.delay = function (timer, callback){
let self = this;
setTimeout(() => {
callback(self);
}, timer);
}
$('#test').delay(5000, function(element) {
$(element).delay(5000, function(element) {
console.log("Here we are!");
});
});
Comments
You cannot delay the execution that way.
Your original delay function, does create a timeout callback, but it also immediately (before the timeout happens) returns itself.
For your example:
$('#test').delay(5000).delay(1000).addClass('red');
the following happens:
- call
$ - call
delayon the result of #1 - call
delayon the result of #2 - call
addClasson the result of #3 - the timeout set in #3 executes and no one cares about the returned result
- the timeout set in #2 executes and no one cares about the returned result
To get the result you desire, you could simply accumulate the desired delay, and apply it at the point of the action, like so:
function abc(elm){
this.$elm = document.querySelector(elm);
this._delayTimeout = 0;
this._delayExec = (cb) => {
window.setTimeout(cb, this._delayTimeout);
}
}
abc.prototype.addClass = function (str){
this._delayExec(() => {
this.$elm.classList.add(str)
});
return this;
}
abc.prototype.removeClass = function (str){
this._delayExec(() => {
this.$elm.classList.remove(str)
});
return this;
}
abc.prototype.delay = function (timer) {
this._delayTimeout += timer;
console.log(this._delayTimeout);
return this;
}
function $(str){
return new abc(str);
}
let x = $('#test').delay(1000).addClass('red').delay(2000).removeClass('red').addClass('green');
console.log($('#test'));
.red {
color: red;
}
.green {
background-color: green;
}
<div id="test">Test</div>
2 Comments
$('#test').delay(1000).addClass('red').delay(5000).removeClass('red').addClass('red')add class red after 1 sec and wait for 5 sec remove class and add class red without wait
asyn await.promise i can use