43
I was researching about callback in Javascript when I found this question:
How to really learn to use Promises (promises) in javascript?
But after all :
- What are promises?
- What are they for?
43
I was researching about callback in Javascript when I found this question:
How to really learn to use Promises (promises) in javascript?
But after all :
41
Promises of javascript is an implementation of the Futures idea of functional programming.
It has become the standard way of working with asynchronous javascript code.
An object preserves the promise that the function it generated will sometime in the future end and return you a response. It can be a positive or negative response. The Promise can be passed to other functions or returned.
There are several implementations of Promise for javascript today. They all end up following this specification.
The advantages of using Names and not callbacks is that you avoid callback Hells and callback cascades that make code hard to read and understand.
EDIT: I have put a more pertinent examples that show the potential of events when you have several callback levels.
Ex with callback.
function isUserTooYoung(id, callback) {
openDatabase(function(db) {
getCollection(db, 'users', function(col) {
find(col, {'id': id},function(result) {
result.filter(function(user) {
callback(user.age < cutoffAge)
})
})
})
})
}
The nesting level can become much higher than this....
with Promises would be like this:
function isUserTooYoung(id) {
return openDatabase(db)
.then(getCollection)
.then(find.bind(null, {'id': id}))
.then(function(user) {
return user.age < cutoffAge;
});
}
Each function does just what it should do and does not need to worry about calling callback or knowing what the function it called is waiting for.
@Guilherme Lautert , How can I improve my answer so that it is accepted? What details do you think were left out?
23
Promises (or Promises) are an abstraction used to represent action flows in asynchronous code, and in Javascript Promise
is an object that represents the result of an asynchronous operation, this result can be successful (generated by the function call resolve
and triggers the call of the method then
) or failed (generated by function call reject
and triggers the call of the method catch
). A simple example to illustrate the concept:
// Aqui criamos uma Promesa que será "resolvida" após o disparo do timer
// (1 segundo)
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
$('body').append('Timer executado<br>');
resolve();
}, 1000);
});
// a função anônima passada como parâmetro para ".then" representa a ação que
// será realizada quando nossa promessa for resolvida/cumprida
p.then(function() {
$('body').append('Promise resolvida<br>');
});
$('body').append('Texto qualquer<br><br>');
<script src="https://cdn.jsdelivr.net/es6-promise/3.1.2/es6-promise.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
In this example setTimeout
is an asynchronous operation that is transformed into a Promise
and assigned the variable p
. So we have the variable p
which represents the promise of some operation that will eventually occur, and in this case it occurs after the time stipulated in the timer, 1 second / 1000 milliseconds, at which time the string is append "'Timer executado<br>'"
and Promise is finished|complete|solved by calling the function resolve
, thus triggering the method then
executing the append function of the string "Promise resolvida"
.
As for the usefulness of Promises, it lies in its ability to represent asynchronous flow in a way that is understandable to the developer. As an example see how is the "traditional/old" mode to represent such a flow in javascript:
algumaFnAsync(function() {
outraAsyncFn(function() {
maisUmaAsyncFn(function() {
// código que faz algo após todas
// as operações assíncronas terem completado
});
});
});
You have asynchronous functions that receive an anonymous function as a parameter, and this function will be executed when that asynchronous function finishes its execution. It is not difficult to see the problem there, in series of asynchronous codes that need to be executed one after the other you end up with various levels of nesting, the so-called callback Hell (did not find a good ref in PT). Promises solve this problem, see how the previous example could be rewritten with the use of them:
algumaFnAsync().then(function() {
return outraAsyncFn();
}).then(function() {
return maisUmaAsyncFn();
}).then(function() {
// código que faz algo após todas as operações assíncronas terem completado
});
The code is clearer in its intention and the representation is much closer to a synchronous flow where you have "do this, then this, then that". Although they are a non-trivial abstraction Precedents are a good solution to the problem that is the representation of asynchronous flow in code.
7
A promise is a "box" (formally, in Javascript, a object) that encapsulates a value that will be obtained from an asynchronous operation. Generally this value comes from I/O operations, which are usually asynchronous.
The promise, as its name says, "promises" eventually provide a value in a moment unknown in relation to the creation of the promise. How the receipt of this value occurs at a time future in relation to the creation of the promise, it is necessary to use some means to execute some code when the promise has been "finalized" so that the value obtained by the asynchronous operation can be accessed.
The most common way to receive this "promise completion notification" is to use the method then
, running a callback through the resolution promise. There is also the method catch
, executes a callback through possible rejections of promise.
Thus, promises are a type of structures that allow "encapsulating" asynchronous operations in Javascript. They are much more declarative than callbacks, which was the previous medium used to manage this type of operation in JS. Some say promises are primitive for handling asynchronous operations.
An example:
// Nesse exemplo, a função `readFileString` retorna uma promessa que contém uma string.
// Na notação do TypeScript, o tipo desta promessa seria `Promise<string>`.
// Isto é, quando for resolvida, a promessa fornecerá uma string.
readFileString('./foo.txt')
.then((fileContents) => {
// `fileContents` é a string resolvida pela promessa.
console.log('Conteúdo do arquivo:', fileContents);
})
.catch((ioError) => {
// Eventualmente, a promessa também pode ser rejeitada:
console.error(ioError);
});
The promises were natively introduced into Javascript in the Ecmascript 2015 (ES6) edition. There polyfill available, although most of the mainstream browsers support this building natively.
A promise can be seen as a state machine. In this sense, it is relatively simple, having only three states:
When the promise is created, the state is immediately assumed pending
. Eventually, the promise can be "finalized", moving to one of two states:
fulfilled
, when the promise is settled (most of the time with some value). This usually corresponds to an operation performed without errors.rejected
, when the promise is rejected (most of the time with some error). This usually corresponds to an operation that encountered some error.It is also said that the promise is settled
when in the state fulfilled
or rejected
. From now on, we will treat "finished" promises as promises settled.
A promise can only become settled (resolve or reject) a only time, with a view to fulfilled
and reject
sane finals. In other words, it is not possible to revert from these states to the pending
. The direction of the arrows in the diagram above also highlights the impossibility of retreating pending
.
There are three main ways to use a promise:
async
and await
.As we have seen above, any promise has methods such as then
or catch
, which are used respectively to address the resolution and rejection of the promise.
The interesting thing is, from inside the callback passed to these methods, one can return a value, which shall be used by the (then
or catch
) to create a new promise, which by it will be returned. This makes possible the chaining of several then
s and several catch
es.
This is due to the relative nature "pure" of the promises, which, although are not totally monadic, allow composition and chaining, factors that comes from functional programming, one of the inspirations for the promise in JS.
Without further ado, an example:
const username = 'lffg';
// `fetch` retorna uma promessa, do tipo `Promise<Response>`:
fetch(`https://api.github.com/users/${username}`)
.then((response) => {
// Note que, de dentro deste `then`, estamos retornando o resultado do método
// `Response.prototype.json`, que converte a `Response` (resultado da promessa
// anterior) em JSON.
// O método `json` também retorna uma promessa.
return response.json();
})
// <------------------------------- Note o encadeamento.
.then((json) => {
return json.public_repos; // Deste `then`, retornamos número de repositórios do usuário.
})
// <------------------------------- Note o encadeamento.
.then((repoCount) => {
console.log(`O usuário pesquisado possui ${repoCount} repositórios.`);
})
// Por fim, encadeamos um `catch` para tratar eventuais rejeições.
.catch((error) => {
console.log('Houve algum erro: ' + error.message);
});
This chain is at all times possible, given that:
then
or catch
return a promise, the then
(or catch
) will make the "planing" (English, flat) of the promise, so as to return a promise of "depth" 1.then
or catch
return a promise, the then
(or catch
) will cause that value to be wrapped in a promise.More details on Promise.prototype.then
and in Promise.prototype.catch
.
async
and await
for await promisesThe async
is an annotation that can be used to mark functions such as asynchronous. Within asynchronous functions, it is possible to use the operator await
.
This syntactic construction was introduced in Ecmascript 2017 (ES8). Therefore, in some environments, it may not be possible to use it without a transpilation process.
The async
/await
has become extremely common since, for many people, it tends to make asynchronous programming using promises of a little easier understanding.
That’s because the async
/await
give the appearance of synchronism, since, within the asynchronous function, the await
blockade the execution until the promise is settled.
await
will unlock the execution and evaluate to the value solved by the promise.await
unblock execution and launch rejection error.Like the await
error thrower in case of rejection, it is possible to use blocks try
/catch
, which makes the syntax even closer to the idea of synchronization that some programmers have.
Converting the previous example to async
/await
, we have something like:
const username = 'lffg';
// Note que o `await` só pode ser utilizado DENTRO de funções assíncronas:
(async () => {
try {
// O `fetch` retorna uma promessa. Utiliza-se o `await` para aguardar a finalização.
const response = await fetch(`https://api.github.com/users/${username}`);
// O método `Response.prototype.json` retorna uma promessa. Portanto, é necessário
// utilizar o `await`.
const json = await response.json();
// Note que como `json` não é uma promessa, não é preciso utilizar o `await`.
const repoCount = json.public_repos;
console.log(`O usuário pesquisado possui ${repoCount} repositórios.`);
} catch (error) {
console.log('Houve algum erro: ' + error.message);
}
})();
More details in this other question.
A promise is created from the builder Promise
, present in the global scope of Javascript. This constructor must be provided with a function called executor of the promise, that will be invoked immediately after the instantiation of the promise.
The executing function takes two functions as parameters, commonly called resolve
and reject
. When called:
resolve
, when called, resolves the promise (passing it to the state fulfilled
) with the value provided.reject
, when called, rejects the promise (passing it to the state rejected
) with the given value. This value is usually an instance of Error
.An example:
// Promessa que será resolvida após 1 segundo de sua criação.
const promiseThatWillFulfill = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Valor de sucesso, vindo de dentro da promessa.');
}, 1000);
});
// Promessa que será rejeitada após 2 segundos de sua criação.
const promiseThatWillReject = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Whoops! Algo deu errado, vindo de dentro da promessa.'));
}, 2000);
});
//
// Utilização de `promiseThatWillFulfill`:
// =======================================
promiseThatWillFulfill
// O `then` é um método presente em qualquer promessa:
.then((resolvedValue) => {
console.log('Promise `promiseThatWillFulfill` resolvida com: ' + resolvedValue);
})
// Como o `then` retorna uma outra promessa, pode-se encadear um `catch`,
// que também é um método de promessa, para realizar a tratativa da rejeição.
//
// Nesse caso, no entanto, o `catch` não será executado, já que sabemos que a
// promessa `promiseThatWillFulfill` não irá ser rejeitada.
.catch((error) => {
console.log('Algo deu errado em `promiseThatWillFulfill`: ' + error.message);
});
//
// Utilização de `promiseThatWillReject`:
// ======================================
promiseThatWillReject
// Neste caso, o `then` não será chamado:
.then((resolvedValue) => {
console.log('Promise `promiseThatWillReject` resolvida com: ' + resolvedValue);
})
// Será rejeitada:
.catch((error) => {
console.log('Algo deu errado em `promiseThatWillReject`: ' + error.message);
});
Most of the time, however, the programmer will not directly use the constructor Promise
to create a new promise. This is usually done by library creators, who wish to implement the promise interface for methods, functions etc.
Eventually, however, the use of these constructors can be used to "adapt" old functions or methods that were not done with the promise interface, but rather with callbacks, which was the medium ancient of handling asynchronous Javascript operations (at one time sad in which promises did not yet natively exist). Here’s how to adapt old libraries to the promise interface.
Promise
to a variable?Promise
s?Browser other questions tagged javascript promises
You are not signed in. Login or sign up in order to post.
I don’t know if the tag should be promises or Promises :)
– Sergio
Because it’s common terminology in this context, I prefer Promises in the tag of what promises.
– Bacco
Tip: leaves the tag as promises (since this is the OSPt) and makes Promises be his synonym.
– Luiz Vieira
Imagine that Promises are steroid callbacks. Then read the texts.
– user21448
On the day it is Javaescrita, we can speak of Promessas: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
– brasofilo