Resumo : neste tutorial, você aprenderá sobre o padrão de encadeamento de promessas JavaScript que encadeia as promessas para executar operações assíncronas em sequência.
Introdução ao encadeamento de promessas JavaScript
Às vezes, você deseja executar duas ou mais operações assíncronas relacionadas, onde a próxima operação começa com o resultado da etapa anterior. Por exemplo:
Primeiro, crie uma nova promessa que resolva o número 10 após 3 segundos:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
Linguagem de código: JavaScript ( javascript )
Observe que a setTimeout()
função simula uma operação assíncrona.
Em seguida, invoque o then()
método da promessa:
p.then((result) => {
console.log(result);
return result * 2;
});
Linguagem de código: JavaScript ( javascript )
O retorno de chamada passado para o then()
método é executado assim que a promessa é resolvida. No callback, mostramos o resultado da promessa e retornamos um novo valor multiplicado por dois ( result*2
).
Como o then()
método retorna um new Promise
com um valor resolvido para um valor, você pode chamar o then()
método no retorno Promise
assim:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result);
return result * 2;
}).then((result) => {
console.log(result);
return result * 3;
});
Linguagem de código: JavaScript ( javascript )
Saída:
10
20
Neste exemplo, o valor de retorno do primeiro then()
método é passado para o segundo then()
método. Você pode continuar chamando o then()
método sucessivamente da seguinte maneira:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result); // 10
return result * 2;
}).then((result) => {
console.log(result); // 20
return result * 3;
}).then((result) => {
console.log(result); // 60
return result * 4;
});
Linguagem de código: JavaScript ( javascript )
Saída:
10
20
60
A maneira como chamamos os then()
métodos dessa forma costuma ser chamada de cadeia de promessas.
A imagem a seguir ilustra a cadeia de promessas:
Vários manipuladores para uma promessa
Quando você chama o then()
método várias vezes em uma promessa, não é o encadeamento da promessa. Por exemplo:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result); // 10
return result * 2;
})
p.then((result) => {
console.log(result); // 10
return result * 3;
})
p.then((result) => {
console.log(result); // 10
return result * 4;
});
Linguagem de código: JavaScript ( javascript )
Saída:
10
10
10
Neste exemplo, temos vários manipuladores para uma promessa. Esses manipuladores não têm relacionamentos. Além disso, eles são executados de forma independente e não passam o resultado de um para outro como a cadeia de promessas acima.
A imagem a seguir ilustra uma promessa que possui vários manipuladores:
Na prática, você raramente usará vários manipuladores para uma promessa.
Devolvendo uma promessa
Quando você retorna um valor no then()
método, o then()
método retorna um novo Promise
que resolve imediatamente o valor de retorno.
Além disso, você pode retornar uma nova promessa no then()
método, assim:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result * 2);
}, 3 * 1000);
});
}).then((result) => {
console.log(result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result * 3);
}, 3 * 1000);
});
}).then(result => console.log(result));
Linguagem de código: JavaScript ( javascript )
Saída:
10
20
60
Este exemplo mostra 10, 20 e 60 a cada 3 segundos. Este padrão de código permite executar algumas tarefas em sequência.
O seguinte modificou o exemplo acima:
function generateNumber(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num);
}, 3 * 1000);
});
}
generateNumber(10)
.then((result) => {
console.log(result);
return generateNumber(result * 2);
})
.then((result) => {
console.log(result);
return generateNumber(result * 3);
})
.then((result) => console.log(result));
Linguagem de código: JavaScript ( javascript )
Sintaxe de encadeamento de promessa
Às vezes, você tem várias tarefas assíncronas que deseja executar em sequência. Além disso, é necessário passar o resultado da etapa anterior para a próxima. Nesse caso, você pode usar a seguinte sintaxe:
step1()
.then(result => step2(result))
.then(result => step3(result))
...
Linguagem de código: JavaScript ( javascript )
Se você precisar passar o resultado da tarefa anterior para a próxima sem passar o resultado, use esta sintaxe:
step1()
.then(step2)
.then(step3)
...
Linguagem de código: CSS ( css )
Suponha que você queira executar as seguintes operações assíncronas em sequência:
- Primeiro, obtenha o usuário do banco de dados.
- Segundo, obtenha os serviços do usuário selecionado.
- Terceiro, calcule o custo do serviço a partir dos serviços do usuário.
As funções a seguir ilustram as três operações assíncronas:
function getUser(userId) {
return new Promise((resolve, reject) => {
console.log('Get the user from the database.');
setTimeout(() => {
resolve({
userId: userId,
username: 'admin'
});
}, 1000);
})
}
function getServices(user) {
return new Promise((resolve, reject) => {
console.log(`Get the services of ${user.username} from the API.`);
setTimeout(() => {
resolve(['Email', 'VPN', 'CDN']);
}, 3 * 1000);
});
}
function getServiceCost(services) {
return new Promise((resolve, reject) => {
console.log(`Calculate the service cost of ${services}.`);
setTimeout(() => {
resolve(services.length * 100);
}, 2 * 1000);
});
}
Linguagem de código: JavaScript ( javascript )
O seguinte usa as promessas para serializar as sequências:
getUser(100)
.then(getServices)
.then(getServiceCost)
.then(console.log);
Linguagem de código: CSS ( css )
Saída
Get the user from the database.
Get the services of admin from the API.
Calculate the service cost of Email,VPN,CDN.
300
Linguagem de código: JavaScript ( javascript )
Observe que o ES2017 introduziu o async
/await
que ajuda você a escrever um código mais limpo do que usar a técnica de encadeamento de promessas.
Neste tutorial, você aprendeu sobre a cadeia de promessas que executa várias tarefas assíncronas em sequência.