Passing Promise to first argument of `.then` - es6-promise

My question is: Is it okay to pass a promise to the first argument of .then? (Assuming that I'm not interested in the returned value of the previous promise and I just want to chain promises together).
Someone told me that if I do this, a new promise will be created
implicitly (unnecessarily), and I might face issues handling errors
bellow in the promise chain.
I know that if you don't explicitly return a promise in an async method the result will be implicitly wrapped. In this case, .then should not wrap the argument in a promise since the argument is already a promise :/
Example:
async function asyncFunc() {
//async function (return Promise)
}
// I know this is okay
somePromise.then(() => asyncFunc());
// BUT... is this okay?
somePromise.then(asyncFunc());

Is it okay to pass a promise to the first argument of .then?
Yes.
Someone told me that if I do this, a new promise will be created implicitly (unnecessarily)
Promise.prototype.then() returns a new promise either way.
// BUT... is this okay?
somePromise.then(asyncFunc());
No, it is more or less the same as:
const p = asyncFunc()
somePromise.then(p);
You execute the function before somePromise actually resolves. What you probably want instead is somePromise.then(asyncFunction). This will properly chain the promises after each other.
Someone told me that [...] I might face issues handling errors bellow in the promise chain.
No. This does not change the behaviour of the promise chain as long as long as there is a catch at the end of the chain.

Related

How to understand the introduction of Promise.resolve in the reduce method of Array

const tasks = [f1, f2, f3];
tasks.reduce(async (promise, task) => {
await promise;
await task();
}, Promise.resolve)
1、The role of Promise.resolve
2、The role of await promise;
Thanks~~
This design pattern using .reduce() is to serialize a number of promise-returning operations. As such, the logic is that you wait on the previous promise, then when it's done you execute your next task and return a promise as value for the next cycle through the loop where the process can be repeated.
To make that first iteration work without special code for the first iteration, you need a promise that you can initially wait for. So, you pass an already resolved promise created with Promise.resolve() to "prime the pump" and give it an initial promise to use.
If you unwrap the .reduce() loop, in your example, you essentially end up with this:
Promise.resolve().then(f1).then(f2).then(f3)
Starting the chain with Promise.resolve() avoids special casing the first iteration of the loop.
That could be written as:
f1().then(f2).then(f3)
But, that special cases the first task which really complicates using something like .reduce() which is simplest when you do the same thing with every iteration of the loop. So, starting things off with Promise.resolve() allows the first iteration to do exactly the same thing as all the other iterations.
As for your two bullet points:
The role of Promise.resolve()
To give .reduce() an initial promise for the first iteration to wait for.
The role of await promise
That waits until the task from the previous iteration of the loop is done before calling the next task.
Note: To fully understand this code, you have to fully understand how .reduce() works. You pass it two arguments, your callback function and an initial value. That initial value is passed to the first iteration of the callback as the first argument to the callback (what you named promise).
Then, whatever value you return from that callback will be passed as the value to the next iteration of the callback. Since you're using an async callback which ALWAYS
returns a promise, your callback will always return a promise which is what will get passed to the next iteration of the callback. And, because the first thing your callback does is await promise, you end up "chaining" promises which serializes the execution of your tasks.

Why a lambda cannot make the enclosing function return?

I'm quite new to Kotlin. I hit this part while I was going over the docs:
"a lambda cannot return from the enclosing function" (unless it's inlined).
So, this doesn't work;
fun foo() {
ordinaryFunction {
return // ERROR: cannot make `foo` return here
}
}
I wonder why it works that way?
The only thing I can think of it's dangerous since there might be some extra stuff the enclosing function might be doing after the lambda execution. But I'm not sure that's the reason because you can overcome this by using qualified returns or using inline keyword. So, that kind of implies there's a technical reason behind it (apart from any usability/safety reasons) like the compiler cannot figure out where to return unless it's labeled or inlined.
Any help would be great!
The problem is here that non-local returns can't be done on the JVM.
If you want to return from lambda (local return) you can add label #ordinaryFunction:
fun foo() {
ordinaryFunction {
return#ordinaryFunction
}
}
Docs say:
If we need to return from a lambda expression, we have to label it and qualify the return. Oftentimes it is more convenient to use implicit labels: such a label has the same name as the function to which the lambda is passed. In our case it is #ordinaryFunction.
Someone else can probably explain this better but in pretty much any programming language, when you call a function, a new entry is created on top of the stack. The stack keeps information about the arguments that the function was called with and the place you should return to when the function completes.
Kotlin doesn't have a feature that lets you return from multiple function calls in one return, so you have to return from each function call manually.
When you inline a function the machine code that would normally execute in a separate subroutine is now copy pasted to the function call site instead. That's why return from an inline function actually returns from the function that called the inlined lambda.
there might be some extra stuff the enclosing function might be doing after the lambda execution.
The problem is the other way around: the lambda can "escape" from the enclosing function's scope and end up executing after the function returns. E.g. consider
fun foo() {
Thread(Runnable {
Thread.sleep(1000)
return
})
}
Or just
fun foo() = // lambda
In either case it makes no sense for the lambda to return from foo, does it? And the compiler doesn't know if your ordinaryFunction lets the lambda escape foo's scope unless it's inline.
you can overcome this by using qualified returns
That's not really overcoming, that's just not returning from the enclosing function.

Promise.resolve inside then() method does not pass its resolved value

I found an interest thing about Promise. When I run the following codes, it gave me the output of 'aa' as oppose to 'bb', which confused me a lot. Does anyone understand why and give a explanation, please? Thanks!
Promise.resolve('aa')
.then(Promise.resolve('bb'))
.then(console.log);
Well, you're misusing a .then() handler so it is no surprise that you don't get the desired answer.
A .then() handler should be passed a function reference. You are passing it a promise which it dutifully ignores because it's not a callable function.
When you do this:
.then(Promise.resolve('bb'))
That executes Promise.resolve('bb') immediately and passes the return result (which is a promise) to .then(). So, you're passing a promise to .then() when you should be passing a function reference. If you change your code to this, then you will get what you expect:
Promise.resolve('aa')
.then(function() {return Promise.resolve('bb');})
.then(console.log);
Remember, the point of passing something to .then() is that it can be executed LATER when the parent promise resolves/rejects. So, for that to be possible, you have to pass a function reference that can be called by the promise infrastructure at some later time.
Using ES6 syntax, you could shorten to this:
Promise.resolve('aa')
.then(_ => Promise.resolve('bb))
.then(console.log);

Jquery deferred.done doesn't recognize result type of function

I created the code below which generates the error: Uncaught TypeError: Cannot read property 'done' of undefined. I think I understand what's happening here, def() isn't a deferred until the timeout expires and the .done tries to run straight away, but what I don't understand is if this doesn't work, why do deferreds work at all? How does .done ever know that the code in front is a promise/deferred given that it may not have resolved yet? Please explain syntax that will make it work, because this is doing my head in.
To put it bluntly I wish that .done would just shut up and wait like it's meant to (I understand that it would have to be a method of all objects and wait until they've resolved even if it's not to a deferred, but if you've typed .done why wouldn't you want that?). Or does it work that way, but I just don't know how to use it properly?
Please don't just refer me to an existing guide/post on jquery deferred unless it explicitly resolves my confusion.
Thanks.
jsfiddle here
function def() {
d = new $.Deferred;
setTimeout(function(){
d.resolve();
return d;
},1000)
}
def().done(function(){
console.log('test');
});
You have to return the promise value from def() itself, not from the setTimeout().
function def() {
var d = $.Deferred();
setTimeout(function(){
d.resolve();
},1000)
return d;
}
def().done(function(){
console.log('test');
});
Returning a value from setTimeout() doesn't do anything. def() has long since finished executing (and returning nothing) and the return value from setTimeout() just goes back into part of the system runtime that calls timer callbacks and is ignored.
I also made a couple other corrections:
Declared d as a local variable (not an implicit global) by putting var in front of its declaration.
Changed the creation of the deferred to $.Deferred(). While, I think the new construction might work, that isn't how jQuery has documented its usage.

Node js: Assign mysql result to requests

Previously I was PHP developer so this question might be stupid to some of you.
I am using mysql with node js.
client.query('SELECT * FROM users where id="1"', function selectCb(err, results, fields) {
req.body.currentuser = results;
}
);
console.log(req.body.currentuser);
I tried to assign the result set (results) to a variable (req.body.currentuser) to use it outside the function, but it is not working.
Can you please let me know a way around it.
The query call is asynchronous. Hence selectCb is executed at a later point than your console.log call. If you put the console.log call into selectCb, it'll work.
In general, you want to call everything that depends on the results of the query from the selectCb callback. It's one of the basic architectural principles in Node.JS.
The client.query call, like nearly everything in node.js, is asynchronous. This means that the method just initiates a request, but execution continues. So when it gets to the console.log, nothing has been defined in req.body.currentuser yet.
You can see if you move the console log inside the callback, it will work:
client.query('SELECT * FROM users where id="1"', function selectCb(err, results, fields) {
req.body.currentuser = results;
console.log(req.body.currentuser);
});
So you need to structure your code around this requirement. Event-driven functional programming (which is what this is) can be difficult to wrap your head around at first. But once you get it, it makes a lot of sense.