Why does NodeJS NOT use Promise for the readFile API? - javascript

In the book https://pragprog.com/book/tbajs/async-javascript, I found this:
Node’s early iterations used Promises in its nonblocking API. However,
in February 2010, Ryan Dahl made the decision to switch to the
now-familiar callback(err, results...) format, on the grounds that
Promises are a higher-level construct that belongs in “userland.”
It looks quite confusing to me, because as an API to read files, this
fs.readFile('/etc/passwd')
.onSuccess(function(data){console.log(data)})
.onError(function(err){throw err})
looks much better than this:
fs.readFile('/etc/passwd', function (err, data) {
if (err) throw err;
console.log(data);
});
Does anyone have ideas about why "Promises are a higher-level construct" will stops itself from being used in NodeJS API?

Node v8 ships with util.promisify that converts callback APIs to promises, Node v10 ships with native promises support (experimental):
const fs = require('fs').promises;
// in an async function:
let data = await fs.readFile('/etc/passwd');
console.log(data);
The future is promises:
NodeJS will use promises for the new APIs. In fact it is currently discussed how. An earlier attempt in 0.2 to use Promises in node years ago failed because of friction and performance issues.
What has to happen first:
Now promises are a native language feature, but the following has to happen before they make it to the core APIs:
Promises have to be a native language construct this already happened.
The NodeJS and io.js merger that was recently announced has to happen - the time frame is a few short months probably.
The v8 (JavaScript engine) team has to finish working on private symbols which will enable fast promise creation. At the moment the promise constructor is the only way to create promises in native promises and it allocates a closure which is relatively expensive. This is currently being done with Domenic working in tight coordination between the io.js and v8 team to ensure this is done properly.
The v8 team has to optimize the promise implementation, currently native promises lose consistently to userland implementations like bluebird. This is also happening now.
Once all these happen the API will be forked and a version containing promises will be integrated into core. Here is a long and uninteresting discussion about it - there is a better one at the io.js/NG repo but neither are really too informative.
What can be done today
Libraries like bluebird give you tools to instantly convert a callback API to promises in a fast and efficient way. You can use them today and get that functionality.

Historically callbacks are the default for performance reasons, but...
Update 2017 / Node 8: Promises are now supported by the core!
Node.js supports promises since Node v8.x. The APIs are all still written in callback style (for backwards compatibility etc.), but there now is a utility class in node core to convert the callback-based APIs to promise-based APIs (similarly to bluebird):
https://nodejs.org/api/util.html#util_util_promisify_original
From the Node.js docs:
For example:
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
// Do something with `stats`
}).catch((error) => {
// Handle the error.
});
Or, equivalently using async functions:
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
async function callStat() {
const stats = await stat('.');
console.log(`This directory is owned by ${stats.uid}`);
}

Update 2018 / Node 10: New fs.promises API
The fs.promises API provides an alternative set of asynchronous file system methods that return Promise objects rather than using callbacks. The API is accessible via require('fs').promises.
https://nodejs.org/api/fs.html#fs_fs_promises_api
(experimental at this moment, but working perfectly on node latest)

Promises is a library, when using promise it requires to return Promise constructor from function but using callback function chaining same thing is achievable that's why "Promises are a higher-level construct"
Reference: Promises in node js

Related

When to use 'async' built-in for ES2017 or import 'npm i async'

I recently learned that async/await is built into ES2017, but I have made several projects that I needed to require the package async in order to use async/await.
Is there an easy way to tell when I can access async normally or when I need to import it? Do I ever need to use that npm package? What is the purpose of the async package (which currently shows 47,469,002 weekly downloads) if the exact same functionality is now built into the language?
For an example project that requires async feel free to look at the Local-Library MongoDB/Express/Node tutorial project on MDN.
Since this is an Express app (as several of my own are), does this have anything to do with ExpressJS?
I have looked around for about a bit trying to find these answers but have come up empty-handed. Any help understanding this is appreciated.
The async library on NPM provides a number of utility functions for managing asynchronous operations. That is very different than the async keyword in the language that allows you to use await with promises. These are like cats and dogs. They both have something to do with asynchronous programming, but other than that, they really aren't the same thing at all.
For example, suppose you need to make 1000 separate requests to a particular host, but for a variety of reasons (memory consumption, rate limiting by the host, etc...), you cannot have more than 5 requests to target host in flight at any given time. So, you want to launch 5 requests and then each time one finishes, you'll launch another one until you've finally done all 1000.
The async keyword in ES7 could perhaps be used in some custom code to implement the algorithm above I described, but by itself, it doesn't give you that solution.
Whereas the async library from NPM has a specific function in its toolkit for doing exactly what I described. It's called parallelLimit() and it lets you specify exactly how many operations you want to be in parallel at a time (with no more than that). In fact, the async library contains all sorts of utility functions for managing asynchronous control flow and you can see a whole list of them here: https://caolan.github.io/async/v3/docs.html#parallelLimit.
Now that we have the async keyword in the language, some of those algorithms are no longer needed because it's very easy to code them in plain ES7. For example if you want to iterate over an array one at a time, calling an asynchronous function on each item, you can just use a for loop and await, all inside an async function.
async function run() {
for (let x of myArray) {
await doSomeAsyncOperation(x);
}
}
Before we had async and await in ES7, you would have had to either write a bit of custom code to do this asynchronous, serialized iteration or you would use a pre-built function from a library such as the async library.
Summary
To review, the async library contains a number of utility functions for managing asynchronous operations. Some of those are no longer necessary because of the control flow options that async and await provide in ES7 and some are still helpful/useful even with the presence of async and await.
FYI, the async library was originally developed before we even had promises and async/await in Javascript and it dealt with the older-style asynchronous operations that used plain callbacks to signal completion or error and offered utilities for managing them. Promises and async/await have replaced the need for some of the functionality in the async library, but not all.
When to use 'async' built-in for ES2017 or import 'npm i async'
Use the built-in ES7 async/await when it directly and simply solves the asynchronous control flow problem you need to solve. Use a function from the async library when you can't easily solve your problem with just async/await and the async library contains a pre-built function that solves your problem directly and simply.
So, the async library is just one of hundreds of thousands of libraries on NPM. You use it when it contains something that helps you solve your job better than what is already built-into the language, the same logic for when to use any other module from NPM.
aysnc/await that are part of ES2017 enables cleaner style there by avoiding promise chains. See the below example mentioned in mdn. You avoid promise chains like then, catch and yet have asynchronous behaviour
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Async library that you mentioned is more of a utility( they mainly designed to use with node js), It takes the array of callbacks, executes and wraps the them and gives you a promise. Iy also enables you with lot more features like in case you want invoking callback in parallel, serial, chain the callbacks, there by helping track these with a common success/error handling

What are Promises in MongoDB?

I am currently working on a project with mongoDB and am receiving this notification in the terminal:
"DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html"
I am fairly new to mongo and have no idea what these "promises" are. I also checked out the link in the notification, but still cannot understand what it is saying.
If someone could please explain what "promises" are within mongodb and what I should do about this deprecation, that would be great. Thanks!
Promises in MongoDB are just like promises in the larger JS ecosystem. They are an alternative to callback functions which allow for step-by-step orderly execution of asynchronous code.
As your Mongo link, shows, for example, you can use Promise.then() instead of a callback function.
Here is some further discussion.
Here are some other promise implementations:
Bluebird
jQuery
Native ES6/ES2015+ Promises

How to make multiple asynchronous callouts in a NodeJS/Express API

I need to abstract a set of REST APIs in to one simple to use API. I was planning on creating a simple nodejs/express API that makes the individual callouts asynchronously and then returns all of the results at one time.
The JS scene changes rapidly and a lot of information I've seen seems to be outdated. I was hoping someone could give me some advice and point me in the way of the best practices or frameworks that might be set up for a scenario like this.
This just sounds like a simple Express app - nothing complicated. I'd use the request-promise module to give you a nice promise-based interface for making requests of other hosts and then use promises to coordinate the multiple requests into one response.
Other than that, you'd have to show us more details on exactly what you're trying to do for us to offer more specifics.
Here's a rough outline example if you just wanted to make three simultaneous requests and then combine the results:
const rp = require('request-promise');
const express = require('express');
const app = express();
app.get('/getAll', (req, res) => {
// construct urls
let p1 = rp(url1);
let p2 = rp(url2);
let p3 = rp(url3);
Promise.all([p1, p2, p3]).then(results => {
// construct full response from the results array
req.send(fullResponse);
}).catch(err => {
res.status(500).send(err.message);
});
});
app.listen(80);
EDIT Jan, 2020 - request() module in maintenance mode
FYI, the request module and its derivatives like request-promise are now in maintenance mode and will not be actively developed to add new features. You can read more about the reasoning here. There is a list of alternatives in this table with some discussion of each one. I have been using got() myself and it's built from the beginning to use promises and is simple to use.
Personally, I use async for nodejs (Link Here), the async.parallel method takes an array of ajax calls, each with it's own optional callback, as well as a callback for when all are done.

return deferred or deferred.promise() [duplicate]

What are the differences between Deferreds, Promises and Futures?
Is there a generally approved theory behind all these three?
These answers, including the selected answer, are good for introducing promises
conceptually, but lacking in specifics of what exactly the differences are in
the terminology that arises when using libraries implementing them (and there
are important differences).
Since it is still an evolving spec, the answer currently comes from attempting to survey both references (like wikipedia) and implementations (like jQuery):
Deferred: Never described in popular references,
1
2
3
4
but commonly used by implementations as the arbiter of promise resolution (implementing resolve and reject).
5
6
7
Sometimes deferreds are also promises (implementing then),
5
6
other times it's seen as more pure to have the Deferred only
capable of resolution, and forcing the user to access the promise for
using then.
7
Promise: The most all-encompasing word for the strategy under discussion.
A proxy object storing the result of a target function whose
synchronicity we would like to abstract, plus exposing a then function
accepting another target function and returning a new promise.
2
Example from CommonJS:
> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(printResult);
44
Always described in popular references, although never specified as to
whose responsibility resolution falls to.
1
2
3
4
Always present in popular implementations, and never given
resolution abilites.
5
6
7
Future: a seemingly deprecated term found in some popular references
1
and at least one popular implementation,
8
but seemingly being phased out of discussion in preference for the term
'promise'
3
and not always mentioned in popular introductions to the topic.
9
However, at least one library uses the term generically for abstracting
synchronicity and error handling, while not providing then functionality.
10
It's unclear if avoiding the term 'promise' was intentional, but probably a
good choice since promises are built around 'thenables.'
2
References
Wikipedia on Promises & Futures
Promises/A+ spec
DOM Standard on Promises
DOM Standard Promises Spec WIP
DOJO Toolkit Deferreds
jQuery Deferreds
Q
FutureJS
Functional Javascript section on Promises
Futures in AngularJS Integration Testing
Misc potentially confusing things
Difference between Promises/A and Promises/A+
(TL;DR, Promises/A+ mostly resolves ambiguities in Promises/A)
In light of apparent dislike for how I've attempted to answer the OP's question. The literal answer is, a promise is something shared w/ other objects, while a deferred should be kept private. Primarily, a deferred (which generally extends Promise) can resolve itself, while a promise might not be able to do so.
If you're interested in the minutiae, then examine Promises/A+.
So far as I'm aware, the overarching purpose is to improve clarity and loosen coupling through a standardized interface. See suggested reading from #jfriend00:
Rather than directly passing callbacks to functions, something which
can lead to tightly coupled interfaces, using promises allows one to
separate concerns for code that is synchronous or asynchronous.
Personally, I've found deferred especially useful when dealing with e.g. templates that are populated by asynchronous requests, loading scripts that have networks of dependencies, and providing user feedback to form data in a non-blocking manner.
Indeed, compare the pure callback form of doing something after loading CodeMirror in JS mode asynchronously (apologies, I've not used jQuery in a while):
/* assume getScript has signature like: function (path, callback, context)
and listens to onload && onreadystatechange */
$(function () {
getScript('path/to/CodeMirror', getJSMode);
// onreadystate is not reliable for callback args.
function getJSMode() {
getScript('path/to/CodeMirror/mode/javascript/javascript.js',
ourAwesomeScript);
};
function ourAwesomeScript() {
console.log("CodeMirror is awesome, but I'm too impatient.");
};
});
To the promises formulated version (again, apologies, I'm not up to date on jQuery):
/* Assume getScript returns a promise object */
$(function () {
$.when(
getScript('path/to/CodeMirror'),
getScript('path/to/CodeMirror/mode/javascript/javascript.js')
).then(function () {
console.log("CodeMirror is awesome, but I'm too impatient.");
});
});
Apologies for the semi-pseudo code, but I hope it makes the core idea somewhat clear. Basically, by returning a standardized promise, you can pass the promise around, thus allowing for more clear grouping.
What really made it all click for me was this presentation by Domenic Denicola.
In a github gist, he gave the description I like most, it's very concise:
The point of promises is to give us back functional composition and error bubbling in the async world.
In other word, promises are a way that lets us write asynchronous code that is almost as easy to write as if it was synchronous.
Consider this example, with promises:
getTweetsFor("domenic") // promise-returning async function
.then(function (tweets) {
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
})
.then(doHttpRequest) // promise-returning async function
.then(
function (responseBody) {
console.log("Most recent link text:", responseBody);
},
function (error) {
console.error("Error with the twitterverse:", error);
}
);
It works as if you were writing this synchronous code:
try {
var tweets = getTweetsFor("domenic"); // blocking
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
console.log("Most recent link text:", responseBody);
} catch (error) {
console.error("Error with the twitterverse: ", error);
}
(If this still sounds complicated, watch that presentation!)
Regarding Deferred, it's a way to .resolve() or .reject() promises. In the Promises/B spec, it is called .defer(). In jQuery, it's $.Deferred().
Please note that, as far as I know, the Promise implementation in jQuery is broken (see that gist), at least as of jQuery 1.8.2.
It supposedly implements Promises/A thenables, but you don't get the correct error handling you should, in the sense that the whole "async try/catch" functionality won't work.
Which is a pity, because having a "try/catch" with async code is utterly cool.
If you are going to use Promises (you should try them out with your own code!), use Kris Kowal's Q. The jQuery version is just some callback aggregator for writing cleaner jQuery code, but misses the point.
Regarding Future, I have no idea, I haven't seen that in any API.
Edit: Domenic Denicola's youtube talk on Promises from #Farm's comment below.
A quote from Michael Jackson (yes, Michael Jackson) from the video:
I want you to burn this phrase in your mind:
A promise is an asynchronous value.
This is an excellent description: a promise is like a variable from the future - a first-class reference to something that, at some point, will exist (or happen).
A Promise represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise of having a value at some point in the future.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
The deferred.promise() method allows an asynchronous function to prevent other code from interfering with the progress or status of its internal request. The Promise exposes only the Deferred methods needed to attach additional handlers or determine the state (then, done, fail, always, pipe, progress, state and promise), but not ones that change the state (resolve, reject, notify, resolveWith, rejectWith, and notifyWith).
If target is provided, deferred.promise() will attach the methods onto it and then return this object rather than create a new one. This can be useful to attach the Promise behavior to an object that already exists.
If you are creating a Deferred, keep a reference to the Deferred so that it can be resolved or rejected at some point. Return only the Promise object via deferred.promise() so other code can register callbacks or inspect the current state.
Simply we can say that a Promise represents a value that is not yet known where as a Deferred represents work that is not yet finished.
A promise represents a value that is not yet known
A deferred represents work that is not yet finished
A promise is a placeholder for a result which is initially unknown while a deferred represents the computation that results in the value.
Reference
http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics

Can I use different promise implementations together?

I've written a script to deploy a web project. It fist uploads a bunch of files via FTP and then sends a request to a chat bot posting a message to https://chat.stackexchange.com/.
I'm new to JavaScript and Node.js, and didn't know about promises when I first wrote the code. I'm now in the process of converting it from using nested callbacks to promises with the Node build-in Promise.
For making the HTTP request to the bot I've been using request. There's another library called request-promise using Bluebird promises. Are these compatible with the built-in promise implementation? Are there any gotchas I have to look out for?
There's a site listing Conformant Promise/A+ Implementations, but neither Node.js nor Chromium is listed there. Does this mean that I can't use them together?
You will have to trust the claim that Request-promise is a drop-in replacement for Request
bluebird is a superset of the current built in Promise implementation in node. That is to say that you can use them interchangeably except that bluebird has more features/methods. Rather than try to mix them I would just use bluebird everywhere.
If you really don't want to, though, it shouldn't make any difference in terms of chaining promises together. The following still logs hello as expected.
let bluebird = require("bluebird");
new bluebird(resolver => resolver())
.then(() => new Promise(resolver => resolver()))
.then(() => console.log("hello"));
Using Promise = require("bluebird") is pretty common as well.
They are compatible. Probably some implementations differ a little bit, but the main Promise flow is the same. Bluebird seems to be faster even than the native Node.JS implementation.

Categories

Resources