Why does my Promise seem to be blocking execution - javascript

Below is a simplification of my code, I'm basicly running a function, that creates a Promise inside the function and returns it. For some reason though, testing with console.time(), it would appear that the code is actually blocking. The x.root function takes roughly 200ms to run and both console.time() tests give pretty much 200ms. Now if I did the age old trick of wrapping the function in setTimeout, the problem disappears, but I'd like to know what I'm doing wrong here?
I'd really prefer being able to create, resolve and reject the promises inside my helper function and then just call my function followed by then and catch without having to create Promises on an earlier level. What's the malfunction here?
parseroot = function(params) {
return new Promise(function(resolve, reject) {
try {
var parsed_html = x.root(params);
x.replacecontents(params.target, parsed_html);
resolve(true);
}
catch(e) {
reject(e);
}
});
}
console.time("Test 1");
console.time("Test 2");
var el = document.querySelector("#custom-element");
el.parseroot({
section:"list",
target: "#list-container",
}).then(function(response) {
console.info("searchresult > list() success");
console.timeEnd("Test 2");
});
console.timeEnd("Test 1");

Promises don't turn synchronous code into asynchronous code.
If the function you pass to Promise blocks, then the promise will block too.

Related

Understanding setTimeout and its implementation in JavaScript Promises

I have the following code:
function MyPromise(configFunction) {
let nextSuccessCallBack = undefined;
let nextResolve = undefined;
configFunction(function(message){
setTimeout(function(){
if(nextSuccessCallBack) {
var result = nextSuccessCallBack(message);
if(result && result.then) {
result.then(nextResolve);
} else {
nextResolve && nextResolve(result);
}
}
})
});
return {
then: function(successCallback) {
nextSuccessCallBack = successCallback;
return new MyPromise(function(resolve) {
nextResolve = resolve;
})
}
}
}
new MyPromise(function(resolve, reject) {
resolve('new message');
}).then(function(message) {
console.log(message);
return 'another message'
}).then(function(message) {
console.log(message)
console.log('here')
})
In this example, it seems that the nextSuccessCallBack is set to be the callback functions within .then, then its value within the setTimeout function is now populated. However, this confuses me. I thought that when we reach the return statement in the constructor, we return the object and effectively stop the function? If that the case then how does the program even get to the setTimeout?
This is not a correct Promise implementation. It clearly has no capabilities for rejections, but also for the implemented fulfilment feature it does not comply with the Promises/A+ specification. Just to give two examples:
It does not comply with rule 2.1.2.2
When fulfilled, a promise must have a value, which must not change.
....nor with rule 2.2.2.3:
If onFulfilled is a function it must not be called more than once.
In your implementation, if you would add a second call to resolve:
new MyPromise(function(resolve, reject) {
resolve('new message'); resolve('new message2');
}).then((function(message) {
console.log(message);
// ... etc
})
...then both calls to resolve would fire the then callback, and show that the promised value was modified after the first time it was set. This is in complete violation of the principle of promises: promises can only resolve once.
It does not comply with rule 2.2.6:
then may be called multiple times on the same promise.
If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.
This does not happen if we use the following code:
let p = new MyPromise(resolve => resolve("value"));
p.then(console.log); // This callback is called
p.then(console.log); // This callback is not called -> violation!
These are basic shortcomings, and this is just the tip of the iceberg.
If you are interested in how it could be implemented in compliance with Promise/A+, then have a look at one I did a few years ago with a step-by-step explanation.
As to your question
how does the program even get to the setTimeout?
When your main code executes this:
new MyPromise(function(resolve, reject) {
resolve('new message');
})
...then the parameter variable configFunction is initialised with that callback function. The MyPromise constructor calls it, passing it the following callback as first argument:
function(message){
setTimeout(function(){
if(nextSuccessCallBack) {
var result = nextSuccessCallBack(message);
if(result && result.then) {
result.then(nextResolve);
} else {
nextResolve && nextResolve(result);
}
}
})
}
So that means that resolve in your main code's callback function is initialised with the above callback function. Then your main code's callback function calls resolve with a string argument. Since resolve is the above callback function, we can see it gets executed with message initialised to "new message". This function executes setTimeout.
The code in the snippet does solve the purpose but, it is confusing as is a bad implementation of a Promise according to the way MDN Uses Promises in JavaScript for better code efficiency and understanding.
The above code can also be written this way:
const examplePromise = new Promise((resolve, reject) => {
resolve("Another Message");
});
console.log("New Message");
examplePromise.then((message) => {
console.log(message);
});
Now, for better understading of the concept of Promises in JavaScript, I'll take another example:
Let's say I want to create a program which says hello and then after 2 seconds says How Are You?
There are two ways of solving this
Just using the setTimeout() function which executes a function after certain period of time
Using promises with setTimeout()
Case I (Using setTimeout()):
console.log("hello"); //Saying hello for the first time
setTimeout(function () {
console.log("How Are You?");
}, 2000); //2000 milliseconds is 2 seconds
Case II (Using Promises)
console.log("hello");
const example = new Promise((resolve) => {
setTimeout(() => {
resolve("How Are You?");
}, 2000);
});
example.then((message) => {
console.log(message);
});
Now, for simple cases like logging a message after 2 seconds do not require Promises. You may use them (No problem) but actually, Promises are used in cases where, you wait for a function to execute a Database Query or you need to wait for a server to give you some HTML Response or while using WebAPIs, etc.
P.S: setTimeout() is just an example. It is not a rule that you always have to use setTimeout() while writing a Promise. If you are fetching data using a WebAPI, you usually write $.ajax(...).then(...) or fetch(...).then(...) instead of setTimeout()

JS promise revealing constructor in YDKJS

I'm reading the Async & Performance book of the YDKJS series and am having trouble wrapping my head around the revealing constructor pattern.
Here's the example the book gives:
function foo(x) {
// start doing something that could take a while
// construct and return a promise
return new Promise( function(resolve,reject){
// eventually, call `resolve(..)` or `reject(..)`,
// which are the resolution callbacks for
// the promise.
} );
}
var p = foo( 42 );
function bar(fooPromise) {
// listen for `foo(..)` to complete
fooPromise.then(
function(){
// `foo(..)` has now finished, so
// do `bar(..)`'s task
},
function(){
// oops, something went wrong in `foo(..)`
}
);
}
bar( p );
I have two questions:
I think the intention is not to expose the resolve and reject logic to the outside, which creates a good separation of concern between the promise logic and what happens next with .then() in the function (in this case bar()) that "listens" to the Promise. Am I on track here?
The example foo() confuses me. In the comment // start doing something that could take a while, what exactly is this? Is this where your async call would be? Shouldn't it be inside the function in the return statement? I don't understand how this would work otherwise.
I think the intention is not to expose the resolve and reject logic to the outside, which creates a good separation of concern
Yes, that and the difficulty of catching exceptions in the deferred pattern, an alternative way to expose the resolvers only to the function that creates the task but not those that consume the result.
The example foo() confuses me. In the comment // start doing something that could take a while, what exactly is this? Is this where your async call would be?
Yes, that's what they meant.
Shouldn't it be inside the function in the return statement?
Yes, indeed it should be. A specific example might be
function delay(x) {
return new Promise(function(resolve) { // construct and return a promise
setTimeout(function() { // start doing something that could take a while
resolve(); // eventually, call one of the resolution callbacks
}, x);
});
}
It's of course possible that starting the task and waiting for its result are two separate statements, so they could in theory be put apart:
function ajax(x) {
var xhr = new XMLHttpRequest();
xhr.open("GET", x);
xhr.send(); // start doing something that could take a while
return new Promise(function(resolve, reject) { // construct and return a promise
xhr.onload = resolve;
xhr.onerror = reject; // eventually, call one of the resolution callbacks
});
}
but that is a bad practise, as when new, open or send throw you would not get a rejected promise back but an exception. So everything from var xhr = … should be inside the promise constructor callback.
For 2., in general and without further details, yes, you are correct; the resolver function passed to Promise constructor executes immediately. One exception would be use of async/await, though async/await does not appear at JavaScript at Question.

Why do we need Promise in JS

I've just read about Promise on both MDN. I can understand the syntax but not sure about why we need it.
Is there a specific case that can only be done by using Promise? Or is it just a way to write cleaner code?
Promises give us the ability to write cleaner code but reducing (or entirely removing) call-back hell.
In addition, callbacks are the backbone of some new syntax features coming in ES2017, such as async functions, which allows an even cleaner way of writing code.
The third thing that promises do is not immediately apparent when you first learn the syntax -- automatic error handling. Promises allow errors to be passed down the chain and handled in one common place without having to put in layers of manual error handling.
Currently, there's nothing that can be done with JavaScript promises that could not be done without them, as the original Promise implementation was also JavaScript code. One of the arguments for using promises is getting rid of the so-called "callback hell", which looks something like this:
setTimeout(function () {
setTimeout(function() {
setTimeout(function() {
// do something
});
});
});
Which can be easily solved by simple giving names to the functions:
setTimeout(doSomething);
function doSomething() {
setTimeout(doSomethingElse);
}
function doSomethingElse() {
// do something
}
So "callback hell" is a misconception, the real problem should be called "anonymous-function hell". And by the way, simply using promises alone will also not prevent that, like in the following sample:
samplePromise().then(function () {
samplePromise().then(function () {
samplePromise().then( function () {
// do something
});
});
});
See a pattern, here? We have once more anonymous functions as the culprit for deep nesting.
That being said, there's one use case that might arguably benefit from a promise, and that is when exceptions from more than one asynchronous call could be caught by the same catch block:
new Promise(function (resolve, reject) {
resolve("Blah");
}).then(function () {
// do something
}).then(function () {
// do something
}).catch(function (reason) {
// error handling
});
Promise objects are used to perform asynchronous functions.
From the 1st line of the MDN docs:
The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future.
It's just for write cleaner code. Look at this:
https://www.npmjs.com/package/q
It says:
On the first pass, promises can mitigate the “Pyramid of Doom”: the situation where code marches to the right faster than it marches forward.
The Promise object is used for asynchronous computations. A Promise
represents a single asynchronous operation that hasn't completed yet,
but is expected in the future.
Here is an example. You can Run it here http://jsbin.com/yumapi/5/edit?html,js,output
function dieToss() {
return Math.floor(Math.random() * 6) + 1;
}
console.log('1');
var promise = new RSVP.Promise(function(fulfill, reject) {
var n = dieToss();
if (n === 6) {
fulfill(n);
} else {
reject(n);
}
console.log('2');
});
promise.then(function(toss) {
console.log('Yay, threw a ' + toss + '.');
}, function(toss) {
console.log('Oh, noes, threw a ' + toss + '.');
});
console.log('3');
This example Illustrates two things:
First, that the handlers we attached to the promise were indeed called after all other code ran, asynchronously.
Second, that the fulfillment handler was called only when the promise was fulfilled, with the value it was resolved with (in our case, the result of the dice toss). The same holds true for the rejection handler.
Credits to Mozilla and Toptotal

using plain jquery for firebase anonymous authentication

I am trying to understand deferred and promise. I dont want to use any library angularfire etc., before understanding the core concept. This is what i am trying to do and always getting a wrong status. Please advise.
........
var defObj = $.Deferred();
var fbref = new Firebase(<<firebase url>>);
defObj.done(function() {
console.log('Success')
}
);
defObj.fail(function() {
console.log('Fail')
}
);
defObj.resolve(
fbref.authAnonymously(function(error, authData) {
if (error) {
defObj.reject();
}
/*
else if (authData) {
defObj.resolve();
}
*/
});
return defObj.promise();
........
Pls ignore any syntax errors. Earlier I wrapped the fbref.authAnonymously call in a seperate function. In debug mode it was falling to fail but in run mode it was always going to success.
I am sure my firebase instance is not enabled for anonymous authentication.
edited : misspelt title.
Promises are now an official part of JavaScript and you can use them in the latest browsers without a library.
function authAnonymously() {
// 1
var promise = new Promise(
function(resolve, reject) {
var ref = new Firebase(<<firebase url>>);
ref.authAnonymously(function(error, authData) {
if (error) {
reject(error); // 2
} else {
resolve(authData); // 3
}
});
});
}
authAnonymously()
.then((authData) => console.log(authData)) // 4
.catch((error) => console.error(error)); // 5
Here are the five steps in this example
Create a Promise constructor
If the asynchronous action is to error, mark it with the reject() function.
If the asynchronous action is to succeed, mark it with the resolve() function.
Call the authAnonymously() function and begin the promise chain with the then() function. When successful this function will fire off.
Continue the promise chain with the error() function. If the error occurs, the catch() function won't fire, but this error() function will.
Promises work well for one time callbacks. For Firebase, this is great for authentication methods and once() calls. This is not great though for repeated callbacks, like the on() function.

Bluebird: How to bind a promise so that I can customize behavior in .catch, and then allow error to continue cascading?

Note- see the update below
I want have a flow with a dependency between the first task to the execution between the other secondary tasks, but the other secondary tasks can all be run concurrently.
I want to write a clean flow which will make it easy to handle errors, and I've tried several variations but can't get it right.
Here's what I will be working with, regardless of the pattern I compose it:
var primaryAsyncTask = {...}; //single 'task' which has an execution function
var secondaryAsyncTasks = [{...}]; //array of tasks with same format as above
function promisifyTask(task){ .... }; //returns a promise which executes the task and appends the resolve/reject functions as the last arguments to the task execution function
Now here's the two options I currently tried:
In promisifyTask, I wrap the rejection handler and bind it to the task, so that I can customize the failure info and then check it upon final catch. In other words, the flow looks like this:
.
function taskRejecter(reject, reason) {
//do something to save info from reason onto this = task
reject();
}
function promisifyTask(task) {
return new Promise(function (resolve, reject) {
var rejecter = taskRejecter.bind(task, reject);
task.execute.apply(null, task.args.concat([resolve, rejecter]));
});
}
//and then when executing:
promisifyTask(primaryAsyncTask)
.then(function () {
return Promise.settle(secondaryAsyncTasks.map(function (task) {
return promisifyTask(task);
}));
})
.then(function onSuccess() {...
})
.catch(function onFail() {
//map all the info from the failed tasks (primary/secondary) to the info saved in it by the taskRejecter.
});
The advantage here is that if the primary task fails, it doesn't execute the secondary tasks and reaches the onFail in the catch... but if it succeeds, it executes them and will reach the onFail only if one of them fails (which is also desired behavior).
Alternatively, which looks much nicer internally, is to bind the promise and catch it, instead of wrapping the rejection handler, and then I can handle everything in a single 'taskFailCatcher' function, so it would look like this:
function onTaskFail(reason){
//do something to save info from reason onto this = task, since it was bound before the catch
}
function promisifyTask(task){
return new Promise(function(resolve, reject) {
task.execute.apply(null, task.args.concat([resolve, reject]));
});
}
function promisifyTaskAndCatch(task){
return promisifyTask(task).bind(task).catch(onTaskFail)
}
//and then when executing:
promisifyTask(primaryAsyncTask)
.then(function (){
return Promise.settle(secondaryAsyncTasks.map(function (task) {
return promisifyTaskAndCatch(task);
}));
})
.then(function onSuccess(){...})
.catch(function onFail(){...})
I like the .bind.catch, but the problem here is twofold:
The flow is not consistent. I don't want to execute the secondary tasks when the primary fails, so I use promisifyTask for the primary (so that it is not caught, and reaches the catch at the end), but I promisifyTaskAndCatch inside the .settle, so that I can easily bind and edit the failure info for the task directly after the rejection.
The .catch here is reached only after the primary fails. Now that I catch all the secondary tasks, the .settle will always receive fulfilled promises, so I reach onSuccess even if a secondary task fails.
How can I edit this flow so that I make use of the best of both worlds (.bind.catch for error handling, with a consistent and clear flow)?
-----------------UPDATE------------------
I almost figured this out. I changed it by removing promisifyTaskAndCatch and changing promisifyTask to be:
function promisifyTask(task) {
var promise = new Promise(function (resolve, reject) {
task.execute.apply(null, task.args.concat([resolve, reject]));
});
promise.bind(task).catch(onTaskFail);
return promise;
}
Now the syntax is consistent and the error cascades through, and I also get my error reporting.
The only problem is now that I don't have a guarantee that the internal catch for the task will happen before the external final catch (with the onFail at the end of the chain), since this is async.
Is there a way to return the caught promise, but still have it fail? can I do this without just rethrowing an error inside of .catch ?
The only problem is now that I don't have a guarantee that the internal catch for the task will happen before the external final catch (with the onFail at the end of the chain), since this is async
Actually you do have, since the .catch(onTaskFail) is invoked first the onTaskFail would be executed before the final one. But you are right, if the final catch depends on things that onTaskFail does then it would be much cleaner to actually return a promise for that result.
Is there a way to return the caught promise, but still have it fail?
I think re-throwing the reason would be the best.
Or you even don't have them fail, and use Promise.all and inspect the task objects about their results instead of using Promise.settle and its PromiseInspection values. As you say the reason is saved on the tasks, the most consistent flow would be to return the task objects:
function onTaskFail(reason){
this.error = reason; // or so
return this;
}
runTask(primaryAsyncTask).then(function(primResult) {
return Promise.all(secondaryAsyncTasks.map(function (task) {
return runTask(task).bind(task).catch(onTaskFail);
}));
}).then(function(taskResults) {
// test for errors in the secondary results
// and throw them if you want the global onFail
// else do onSuccess()
}).catch(onFail);
can I do this without just rethrowing an error inside of .catch ?
Yes, you can also return a rejected promise. That might be a Promise.reject(reason), but simpler might be to return promise that is already there (though not currently in scope of onTaskFail). The .return() helper method could be used here though:
…
return promise.bind(task).catch(onTaskFail).return(promise);

Categories