Well i have this function here that runs on intervals and what it does is, when it runs, it sets 2 settimeout.
Here's the problem, an asynchronous function that should be called after the 2nd time out is called before the 2nd timeout is even triggered. This is my code.
var runner = Interval.run(function() {
//-212965881
bot.sendMessage('-212965881', "Drop usernames now").then(function(){
ready = 1;
list = {};
console.log(ready);
setTimeout(function(){
return bot.sendMessage('-212965881',"Round has begun. Please start liking now. Leech check will begin in 1 minute");
}, 10000);
}).then(function(){
ready = 0;
setTimeout(function(){
return bot.sendMessage('-212965881',"Leech check has begun!");
}, 15000);
}).then(function(){
//This one fires before 15 seconds
let msg = {chat:{}};
msg.chat.id = '-212965881';
return bot.event('/check', msg);
}).catch(function(err){
console.log(err);
});
}, 20000);
Not sure why this happens. Perhaps im going about it the wrong way.
Can anyone throw some light on this? Thanks
This happens because the code inside your then handlers are creating un-returned asynchronous code, or basically "breaking out" of the Promise chain without notifying the Promise chain of the activities.
You need to wrap your setTimeout inside of a Promise constructor and then also make sure you wait for the interior bot.sendMessage invocations to finish by resolving them inside your new Promises
Change it to use Promise constructors, see Resolving a Promise
var runner = Interval.run(function() {
//-212965881
bot.sendMessage('-212965881', "Drop usernames now").then(function(){
ready = 1;
list = {};
console.log(ready);
return new Promise((resolve) {
setTimeout(function(){
resolve(bot.sendMessage('-212965881',"Round has begun. Please start liking now. Leech check will begin in 1 minute"))
}, 10000);
});
}).then(function(){
ready = 0;
return new Promise((resolve) {
setTimeout(function(){
resolve(bot.sendMessage('-212965881',"Leech check has begun!"))
}, 15000);
});
}).then(function(){
//This one fires before 15 seconds
let msg = {chat:{}};
msg.chat.id = '-212965881';
return bot.event('/check', msg);
}).catch(function(err){
console.log(err);
});
}, 20000);
because the asynchronous functions you were trying to invoke are returned few seconds later. The three .then you wrote works on the first Promise repeatly.
your can use co module or ES6 async/await to control multiple Promise.
Related
In testing I've found that JavaScript Promises are always asynchronous regardless of whether or not they contain any asynchronous functions in their chain.
Here is some code that shows the order of operations in console. If you run it you will see that even though every function is synchronous the output shows both of the aPromise() calls being run in parallel, and "surprisingly this happens after run 2 finishes" not happening before run 2 finishes.
function aPromise() {
return new Promise(function(resolve, reject) {
console.log("making promise A")
resolve(bPromise());
console.log("promise A resolved")
});
}
function bPromise() {
return new Promise(function(resolve, reject) {
console.log("making and resolving promise B")
resolve();
});
}
aPromise().then(function() {
console.log("finish run 1");
}).then(function() {
console.log("surprisingly this happens after run 2 finishes");
});
aPromise().then(function() {
console.log("finish run 2");
})
Output to console:
making promise A
making and resolving promise B
promise A resolved
making promise A
making and resolving promise B
promise A resolved
finish run 1
finish run 2
surprisingly this happens after run 2 finishes
So, Why are JavaScript promises asynchronous when calling only synchronous functions? What is happening behind the scenes that leads to this behavior?
P.S. In order to better understand this I implemented my own Promise system and I found that making synchronous functions happen in the expected order was easy but making them happen in parallel was something I could only accomplish by putting a setTimeout() of a few milliseconds at every resolve (My guess is that this is not what's happening with vanilla promises and that they are actually being multi threaded).
This has been a small problem for one of my programs where I'm traversing a tree applying an array of functions to each node and putting the functions in queue if that node has an asynchronous function already running. Most of the functions are synchronous so the queue is rarely used but upon switching over from callbacks (hell) to Promises I've been having an issue where the queues get used almost always as a result of Promises never running synchronously. It's not a huge problem but it is a bit of a debugging nightmare.
1 Year Later EDIT
I ended up writing some code to deal with this. It's not amazingly thorough, but I've used it with success to solve the issue I was having.
var SyncPromise = function(fn) {
var syncable = this;
syncable.state = "pending";
syncable.value;
var wrappedFn = function(resolve, reject) {
var fakeResolve = function(val) {
syncable.value = val;
syncable.state = "fulfilled";
resolve(val);
}
fn(fakeResolve, reject);
}
var out = new Promise(wrappedFn);
out.syncable = syncable;
return out;
}
SyncPromise.resolved = function(result) {
return new SyncPromise(function(resolve) { resolve(result); });
}
SyncPromise.all = function(promises) {
for(var i = 0; i < promises.length; i++) {
if(promises[i].syncable && promises[i].syncable.state == "fulfilled") {
promises.splice(i, 1);
i--;
}
// else console.log("syncable not fulfilled" + promises[i].syncable.state)
}
if(promises.length == 0)
return SyncPromise.resolved();
else
return new SyncPromise(function(resolve) { Promise.all(promises).then(resolve); });
}
Promise.prototype.syncThen = function (nextFn) {
if(this.syncable && this.syncable.state == "fulfilled") {
//
if(nextFn instanceof Promise) {
return nextFn;
}
else if(typeof nextFn == "function") {
var val = this.syncable.value;
var out = nextFn(val);
return new SyncPromise(function(resolve) { resolve(out); });
}
else {
PINE.err("nextFn is not a function or promise", nextFn);
}
}
else {
// console.log("default promise");
return this.then(nextFn);
}
}
The callback passed to a Promise constructor is always called synchronously, but the callbacks passed into then are always called asynchronously (you could use setTimeout with a delay of 0 in a userland implementation to achieve that).
Simplifying your example (and giving the anonymous function's names so I can refer to them) to:
Promise.resolve().then(function callbackA () {
console.log("finish run 1");
}).then(function callbackB () {
console.log("surprisingly this happens after run 2 finishes");
});
Promise.resolve().then(function callbackC () {
console.log("finish run 2");
})
Still gives the output in the same order:
finish run 1
finish run 2
surprisingly this happens after run 2 finishes
Events happen in this order:
The first promise is resolved (synchronously)
callbackA is added to the event loop's queue
The second promise is resolved
callbackC is added to the event loop's queue
There is nothing left to do so the event loop is accessed, callbackA is first in the queue so it is executed, it doesn't return a promise so the intermediate promise for callbackB is immediately resolved synchronously, which appends callbackB to the event loop's queue.
There is nothing left to do so the event loop is accessed, callbackC is first in the queue so it is executed.
There is nothing left to do so the event loop is accessed, callbackB is first in the queue so it is executed.
The easiest way I can think of to work around your problem is to use a library that has an Promise.prototype.isFulfilled function you can use to decide whether to call your second callback synchronously or not. For example:
var Promise = require( 'bluebird' );
Promise.prototype._SEPH_syncThen = function ( callback ) {
return (
this.isPending()
? this.then( callback )
: Promise.resolve( callback( this.value() ) )
);
}
Promise.resolve()._SEPH_syncThen(function callbackA () {
console.log("finish run 1");
})._SEPH_syncThen(function callbackB () {
console.log("surprisingly this happens after run 2 finishes");
});
Promise.resolve()._SEPH_syncThen(function callbackC () {
console.log("finish run 2");
})
This outputs:
finish run 1
surprisingly this happens after run 2 finishes
finish run 2
Your code is fine is you want your promises to run independently and let them execute in their own way, no matter each one complete first. As soon as your code is async, you cannot predict which one will be completed first (due to the async nature of the event loop).
However if you want to catch all your promises after they all completed, you should use Promise.all (which is the equivalent of $.when is jQuery).
See:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
So I'm fairly new to JavaScript and aware of asynchronous functions calls. I have done quite a bit of research and found that if you want to run asynchronous calls in succession of one another, you can use callback functions and promises. Now I have come to understand how both of these implementations are useful if you are running just a few asynchronous functions. I'm trying to tackle a completely different animal; at least to my knowledge. I'm currently building a site that needs to appear as if it's writing text to itself. Just to clue everyone here in to my JS code, here is the function that writes to the webpage (I'm fairly new so if you think you have a better solution, an example with a small description would be appreciated):
function write(pageText, elementId, delay) {
var element = document.getElementById(elementId);
var charCount = 0;
setInterval(function() {
if (charCount > pageText.length) {
return;
} else {
element.innerHTML = pageText.substr(0, charCount++);
}
}, delay);
}
write("This is an example", 'someRandomDiv', 100);
<div id="someRandomDiv">
</div>
With this I'm trying to write a line of text to a webpage one line after another. Essentially I'm use to writing code like such in Java and C#:
function writePassage()
{
var passage=["message one", "message two", "... message n"];
for(var i = 0; i<passage.length; i++)
{
write(passage[i], 'someRandomDiv', 100);
}
}
Obviously since this won't work because the for loop in wirtePassage() will finish executing before just one or two of the asynchronous function calls end. I'm asking if there is a sane solution to this error where I have n asynchronous calls, and I need to have one perform before the next one is triggered. It's worth mentioning that I don't want to just run this loop above and add another variable that just keeps track of how long I should delay each passage that will be written. I would prefer if there was a programmatic way that forces the execution of the function before the next one is called. Thanks for reading this monster question!
There are a few things you'll need to do to get this working.
First, your write function will need an asynchronous interface. As you mentioned it could either take a callback or return a promise. Taking a callback would look something like:
function write(pageText, elementId, delay, callback)
{
var element = document.getElementById(elementId);
var charCount=0;
var interval = setInterval(function(){
if(charCount>pageText.length)
{
clearInterval(interval);
callback();
}
else
{
element.innerHTML = pageText.substr(0,charCount++);
}
}, delay);
}
That calls callback when the full pageText has been written into element. Note that it also clears your interval timer when it's done, which avoids an event loop leak.
Then, you'll need to chain your asynchronous calls using this callback. You can do this quite cleanly with a library such as async:
function writePassage()
{
var passage=["message one", "message two", "... message n"];
async.series(passage.map(function(text){
return function(done){
write(text, 'someRandomDiv', 100, done);
};
}));
}
But it's also not so much trouble to do by hand:
function writePassage()
{
var passage=["message one", "message two", "... message n"];
var writeOne = function() {
if (!passage.length) return;
var text = passage.shift();
write(text, 'someRandomDiv', 100, writeOne);
}
// Kick off the chain.
writeOne();
}
That's just asynchronous recursion. Welcome to JavaScript. :)
A promise-based solution can also be pretty clean. First you need to return a promise from write:
function write(pageText, elementId, delay)
{
return new Promise(resolve) {
var element = document.getElementById(elementId);
var charCount=0;
var interval = setInterval(function(){
if(charCount>pageText.length)
{
clearInterval(interval);
resolve();
}
else
{
element.innerHTML = pageText.substr(0,charCount++);
}
}, delay);
}
}
Then you can create a chain of promises via reduction:
function writePassage()
{
var passage=["message one", "message two", "... message n"];
passage.reduce(function(chain, text) {
return chain.then(function(){
return write(text, 'someRandomDiv', 100, writeOne);
});
}, Promise.resolve());
}
In addition to Bo's answer, here is how you would do it with promises (because promises are awesome!). It is a bit more advanced, but I also find it more elegant (array method call on strings, reduce).
I also used arrow functions. If you need to support old browsers, you may want to replace them with regular functions.
// Return a promise resolved after time ms.
var wait = (time) => new Promise((resolve) => setTimeout(resolve, time));
function write(pageText, elementId, delay){
// Fetch the element.
var element = document.getElementById(elementId);
// Empty the element.
element.innerHTML = '';
// Reduce on each character of pageText with a resolved promise
// as a initialiser, and return the resulting promise.
return Array.prototype.reduce.call(pageText, (promise, char) => {
// Chain to the previous promise.
return promise
// First wait delay ms.
.then(() => wait(delay))
// Then add the current character to element's innerHTML.
.then(() => element.innerHTML += char);
}, Promise.resolve());
}
var messages = ["message one", "message two", "... message n"];
messages.reduce((promise, message) => {
return promise
// Write current message.
.then(() => write(message, "the-element", 100))
// Wait a bit after each messages.
.then(() => wait(400));
}, Promise.resolve());
<div id="the-element"></div>
I am trying to check for the presence of a modal. If the modal is not present then it will place the value of the timer into browser.sleep(). This will give time for the modal to appear. I am having an issue with a for loop in a page object. When I run the code below I do not receive the alert and console.log messages under the if when I force a failure by getting changing the object. Also, I do not receive the Timer expired message.
from page_object file (relevant code)
editVinModal: { get: function () {
return browser.element({id: 'editableVINPart'});
}},
doEditVIN: { value: function () {
modalFailedToAppear = true;
console.log('In doEditVIN');
for(modal_timer = 0 ; modal_timer <= 30; modal_timer++) {
if (!(this.editVinModal)) {
alert('In If');
console.log('Modal failed to appear');
console.log('Under if - modalFailedToAppear: ', modalFailedToAppear);
browser.sleep(modal_timer);
console.log('under if - modal_timer: ',modal_timer);
}
else {
console.log('In else if else loop');
// console.log(browser.isElementPresent(this.editVinModal));
console.log('modalFailedToAppear: ',modalFailedToAppear);
modalFailedToAppear = false;
console.log('modalFailedToAppear: ',modalFailedToAppear);
console.log('modal_timer: ',modal_timer);
break;
}
}
if (modalFailedToAppear){
console.log("Modal is not present within the given time period. Timer has expired.");
}
this.editVinLink.click();
}},
Thanks in advance for
Looks like you're new around here. Welcome!
browser.sleep(), generally speaking, does not belong in your Protractor tests (except for debugging purposes). That's the bad news. The good news is that Protractor actually provides a function that does exactly (I think) what you're trying to do. It's called browser.wait() and it works like this:
browser.wait( function() {
return element(by.id('editableVINpart')).isPresent().then( function(present) {
return present;
});
}, 5000)
.then(function() {
element(by.id('editableVINpart')).click();
}, function() {
console.log('Element not found. :( ');
});
browser.wait() takes two arguments: first, an anonymous function, which it will execute repeatedly until it returns true; second, an amount of time to wait in milliseconds (by the way, browser.sleep() also takes a millisecond wait time, so your for loop is only waiting 465 milliseconds if it iterates all the way through, or about a half second--not very long).
Then, since browser.wait() returns a promise, just like all Protractor functions, we can attach a .then() statement to the end of it, which will execute the first passed-in function if the promise is successful, or the second passed-in function if it is not.
If you often have to wait for an element to be present (and for some reason it isn't synchronized with the Angular page load), it may be useful to you to have a reusable form of the function, like this:
var waitThenClick = function(el) {
browser.wait( function() {
return el.isPresent().then( function(present) {
return present;
});
}, 5000)
.then(function() {
el.click();
}, function() {
console.log('Element with locator: ' + el.locator + ' was not found. :( ');
});
};
Then you could just call it like this, for whatever element you need:
waitThenClick(element(by.id('editableVINpart')));
Good luck! Make sure to get good and clever with asynchronous stuff (especially promises) with problems like this. Protractor promises trip up the best of us.
I'm trying to understand Promise. But here I'm confused.
I want to create a test function that will print 3000 after 3 second, then print 2000 after 2 second, then print 1000 after 1 second. Here is my code:
'use strict';
var Q = require('q');
function delayConsole(timeOut) {
var defer = Q.defer();
setTimeout(function(){
console.log(timeOut);
defer.resolve(2000);
},timeOut);
return defer.promise;
}
// This works
delayConsole(3000).then(function(){
return delayConsole(2000);
}).then(function(){
return delayConsole(1000);
});
// This doesn't work. Why?
delayConsole(3000).then(delayConsole(2000)).then(delayConsole(1000));
There, you call the function delayConsole immediately :
.then(delayConsole(2000))
That is : you don't pass the function but the result of the function call, you don't wait for the promises to be chained.
When you do
then(function(){
return delayConsole(2000);
})
then you pass a function, not the result of that function call. The function can be called when the previous element in the promise chain is solved.
I just thought I'd share that you can make this construction work which is sometimes easier to use:
promise.then(delayConsole(3000)).then(delayConsole(2000)).then(delayConsole(1000));
by changing delayConsole() to this:
function delayConsole(timeOut) {
return function() {
var defer = Q.defer();
setTimeout(function(){
console.log(timeOut);
defer.resolve(2000);
},timeOut);
return defer.promise;
}
}
This way, calling delayConsole() just captures the timeout argument and returns a function that can be called later by the promise .then handler. So, you are still passing a function reference to the .then() handler which lets the promise engine call the internal function sometime later rather than execute it now.
I just implemented my first function that returns a promise based on another promise in AngularJS, and it worked. But before I decided to just do it, I spent 2 hours reading and trying to understand the concepts behind promises. I thought if I could write a simple piece of code that simulated how promises worked, I would then be able to conceptually understand it instead of being able to use it without really knowing how it works. I couldn't write that code.
So, could someone please illustrate in vanilla JavaScript how promises work?
A promise is basically an object with two methods. One method is for defining what to do, and one is for telling when to do it. It has to be possible to call the two methods in any order, so the object needs to keep track of which one has been called:
var promise = {
isDone: false,
doneHandler: null,
done: function(f) {
if (this.isDone) {
f();
} else {
this.doneHandler = f;
}
},
callDone: function() {
if (this.doneHandler != null) {
this.doneHandler();
} else {
this.isDone = true;
}
}
};
You can define the action first, then trigger it:
promise.done(function(){ alert('done'); });
promise.callDone();
You can trigger the action first, then define it:
promise.callDone();
promise.done(function(){ alert('done'); });
Demo: http://jsfiddle.net/EvN9P/
When you use a promise in an asynchronous function, the function creates the empty promise, keeps a reference to it, and also returns the reference. The code that handles the asynchronous response will trigger the action in the promise, and the code calling the asynchronous function will define the action.
As either of those can happen in any order, the code calling the asynchronous function can hang on to the promise and define the action any time it wants.
For the simplicity to understand about the promises in Javascript.
You can refer below example. Just copy paste in a new php/html file and run.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function test(n){
alert('input:'+n);
var promise = new Promise(function(fulfill, reject) {
/*put your condition here */
if(n) {
fulfill("Inside If! match found");
}
else {
reject(Error("It broke"));
}
});
promise.then(function(result) {
alert(result); // "Inside If! match found"
}, function(err) {
alert(err); // Error: "It broke"
});
}
</script>
</head>
<body>
<input type="button" onclick="test(1);" value="Test"/>
</body>
</html>
Click on Test button,
It will create new promise,
if condition will be true it fulfill the response,
after that promise.then called and based on the fulfill it will print the result.
In case of reject promise.then returns the error message.
Probably the simplest example of promises usage looks like that:
var method1 = (addings = '') => {
return new Promise(resolve => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '') => {
return new Promise(resolve => {
console.log('method2' + addings)
resolve(addings + '_adding2');
});
}
method1().then(method2).then(method1).then(method2);
// result:
// method1
// method2_adding1
// method1_adding1_adding2
// method2_adding1_adding2_adding1
That's basic of basics. Having it, you can experiment with rejects:
var method1 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method2' + addings)
reject();
});
}
var errorMethod = () => {
console.log('errorMethod')
}
method1()
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod);
// result:
// method1*
// method2*_adding1
// errorMethod
// method2*
// errorMethod
// method2*
As we can see, in case of failure error function is fired (which is always the second argument of then) and then next function in chain is fired with no given argument.
For advanced knowledge I invite you here.
please check this simple promise code. this will help you to better understand of promise functionality.
A promise is an object that may produce a single value some time in the future: either a resolved value, or a reason that it’s not resolved. A promise may be in one of 3 possible states: fulfilled, rejected, or pending. Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.
let myPromise = new Promise((resolve, reject)=>{
if(2==2){
resolve("resolved")
}else{
reject("rejected")
}
});
myPromise.then((message)=>{
document.write(`the promise is ${message}`)
}).catch((message)=>{
document.write(`the promise is ${message}`)
})
check this out