Programming Models: Sequential, Concurrent, and Parallel
Sequential Programming
- Sequential programming is the traditional approach where tasks are executed one after another.
- Each task must complete before the next one begins.
- It's simple to understand but can be inefficient when dealing with multiple operations.
function task1() { // Task 1 execution } function task2() { // Task 2 execution } task1(); task2(); // Task 2 starts only after Task 1 finishes
Characteristics of Sequential Programming
- Single task at a time.
- Blocking: One operation must complete before the next one starts.
- Example: Reading a file and processing its content one after another.
Concurrent Programming
- Concurrent programming refers to executing multiple tasks in overlapping time periods.
- Tasks don't necessarily execute at the same time, but their progress is interleaved.
function task1() { // Task 1 execution } function task2() { // Task 2 execution } setTimeout(task1, 1000); // Task 1 is delayed task2(); // Task 2 can run before Task 1 completes
Characteristics of Concurrent Programming
- Interleaving tasks: Multiple tasks make progress within the same time frame.
- Non-blocking: Tasks may yield control during their execution.
- Example: A web server handling multiple user requests.
Parallel Programming
- Parallel programming is when multiple tasks run at exactly the same time on multiple processors or cores.
- It is a subset of concurrent programming where tasks are truly simultaneous.
// Parallel execution with multiple threads parallelize(task1, task2);
Characteristics of Parallel Programming
- Simultaneous execution: Tasks are executed at the same time.
- Requires multiple processors/cores.
- Example: Image processing where different parts of an image are processed simultaneously.
Comparing the Three Models
- Sequential: One task at a time, linear execution.
- Concurrent: Multiple tasks progress within the same time period.
- Parallel: Multiple tasks execute at the same time on separate processors.
Example: Cooking Analogy
- Sequential: Cook one dish at a time, finishing one before starting another.
- Concurrent: Start cooking one dish while another is simmering.
- Parallel: Two chefs cooking two dishes at the same time on separate stoves.
Conclusion
- Sequential, concurrent, and parallel programming address different needs.
- Choosing the right model depends on the problem and hardware capabilities.
Introduction to Promises in JavaScript
What is a Promise?
A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation.
const promise = new Promise((resolve, reject) => { // asynchronous operation });
States of a Promise
Promises have three states:
- Pending: Initial state, neither fulfilled nor rejected.
- Fulfilled: The operation completed successfully.
- Rejected: The operation failed.
let promise = new Promise((resolve, reject) => { // initially pending });
Example of Promise Resolution
The resolve()
function signals the success of the asynchronous operation.
const promise = new Promise((resolve, reject) => { setTimeout(() => resolve("Success!"), 1000); }); promise.then(result => console.log(result)); // "Success!" after 1 second
Example of Promise Rejection
The reject()
function is used to signal failure in the operation.
const promise = new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Failure!")), 1000); }); promise.catch(error => console.error(error)); // Error: Failure!
Promise Methods: then
, catch
, finally
-
then()
: Used to handle the success case. -
catch()
: Used to handle errors or rejection. -
finally()
: Runs regardless of the outcome.
promise .then(result => console.log(result)) .catch(error => console.error(error)) .finally(() => console.log("Operation complete"));
Chaining Promises
Promises can be chained to handle sequences of asynchronous operations.
fetchData() .then(data => processData(data)) .then(result => displayResult(result)) .catch(error => handleError(error));
Async/Await: Modern Approach
async
/await
simplifies working with promises by allowing you to write asynchronous code that looks synchronous.
async function fetchData() { try { let data = await fetch('https://api.example.com/data'); console.log(data); } catch (error) { console.error(error); } }
What is Async/Await?
- Async/Await is a syntactic sugar built on top of Promises, introduced in ECMAScript 2017 (ES8).
- It allows you to write asynchronous code that reads and behaves like synchronous code.
- Makes code more readable and easier to maintain, especially for complex chains of Promises.
async function fetchData() { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); }
How async
Works
- When a function is declared as
async
, it automatically returns a Promise. - The
async
keyword allows the use of theawait
keyword within that function.
async function myAsyncFunction() { return "Hello, Async!"; } myAsyncFunction().then(result => console.log(result)); // "Hello, Async!"
- Without
async
, the above function would just return a regular value, not a Promise.
How await
Works
- The
await
keyword is used insideasync
functions to pause the execution of the function until the Promise is resolved. - It makes asynchronous code behave as if it were synchronous, without blocking the main thread.
async function fetchData() { let response = await fetch('https://api.example.com/data'); let data = await response.json(); console.log(data); }
Key Characteristics of await
-
Pauses execution:
await
pauses the function execution until the promise is settled (either resolved or rejected). -
Non-blocking: Even though
await
pauses the async function, it does not block the execution of other code outside the function.
async function demo() { console.log("Start"); let result = await someAsyncTask(); console.log(result); } console.log("Code after async call"); // This will run immediately
Handling Errors with Async/Await
- Instead of using
.catch()
to handle errors in Promises,async/await
allows you to handle errors with try-catch blocks.
async function fetchData() { try { let response = await fetch('https://api.invalid-url.com'); let data = await response.json(); console.log(data); } catch (error) { console.error("An error occurred:", error); } }
Parallelism with Async/Await
- Multiple awaits in a function will run sequentially by default. However, you can execute Promises in parallel by calling them first and then awaiting their resolution.
async function loadData() { let promise1 = fetch('https://api.example.com/data1'); let promise2 = fetch('https://api.example.com/data2'); let [data1, data2] = await Promise.all([promise1, promise2]); console.log(data1, data2); }
Using Promise.all()
with Async/Await
-
Promise.all()
allows you to run multiple asynchronous tasks in parallel and wait for all of them to complete. - This is useful when you have independent asynchronous operations that can be executed simultaneously.
async function getData() { let [result1, result2] = await Promise.all([ fetch('https://api.example.com/data1'), fetch('https://api.example.com/data2') ]); console.log(result1, result2); }
Benefits of Async/Await
- Simplicity: Makes code more readable and easier to maintain compared to Promise chains.
-
Error handling: Uses
try-catch
, making error management more straightforward. - Non-blocking: Code execution continues normally without being blocked by async operations.
Async/Await vs Promises
-
Promises: Use
.then()
and.catch()
for handling asynchronous operations. -
Async/Await: Allows asynchronous code to be written in a synchronous style using
await
andtry-catch
for error handling.
Feature | Promises | Async/Await |
---|---|---|
Syntax | More verbose | Cleaner, more readable |
Error Handling | .catch() |
try-catch |
Execution Style | Chain-based | Synchronous-looking |
Performance | Can be parallelized | Can use Promise.all() for parallelism |
Conclusion
- Async/Await simplifies asynchronous programming by making it more readable.
- It builds on top of Promises and is great for writing cleaner, more maintainable code.
- Always consider combining it with
Promise.all()
for parallelism when needed.
Conclusion
- Promises help manage asynchronous code in a cleaner and more readable way.
- Methods like
then()
,catch()
, andfinally()
offer flexibility. - Async/await provides a simpler syntax for working with promises.
Programming Models: Sequential, Concurrent, and Parallel
Programming Models: Sequential, Concurrent, and Parallel
By Néstor Aldana
Programming Models: Sequential, Concurrent, and Parallel
- 86