Skip to content

Latest commit

 

History

History
239 lines (201 loc) · 5.23 KB

File metadata and controls

239 lines (201 loc) · 5.23 KB

Promises Advanced

Links

Содержание

  • Control promises flow with returning Promise.resolve & Promise.reject
  • Dont make nested "then"
  • Make delay to continue
  • Insert a few records with check of previous
  • Make a chain with promises (waterfall)
  • Promise.all vs Promise.allSettled
  • Race condition: Function finishes or timeout error

Control promises flow with returning Promise.resolve & Promise.reject

new Promise((res, rej) => { rej('here') })

.catch(err => {
  if (err.statusCode === 400) {
    return Promise.reject(err)
  }
  return Promise.resolve(err)
})

.then(r => console.log('then'))

.catch(err => console.log('catch'));

Dont make nested "then"

// Wrong
new Promise((res, rej) => { res() })
.then(() => {
 somePromise()
   .then((data) => console.log(data)) 
})
.then((data) => {
 console.log(data) // "Hello"
})
.catch((err) => console.log('Error occured'))
// Right
new Promise((res, rej) => { res() })
.then(() => somePromise())
.then((data) => {
 console.log(data) // "somePromise" answer
})
.catch((err) => console.log('Error occured'))

Make delay to continue

new Promise((r, j) => setTimeout(r, 5000))
.then(...)

// another option
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
delay(3000).then(() => alert('runs after 3 seconds'));

Insert a few records with check of previous

We want to insert a few records, but want make it sequntially and check if previous inserted well, kinda transaction.

function methodThatReturnsAPromise(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`Processing ${id}`);
      resolve(id);
    }, 1000*id);
  });
}

let result = [2,1,3].reduce( (accumulatorPromise, nextID) => {
  return accumulatorPromise.then((id) => {
    // here we can do check if insertion was correct
    // first will be undefined cuz initialValue is Promise.resolve()
    console.log('Id Of inserted item = ', id)

    return methodThatReturnsAPromise(nextID)
  });
}, Promise.resolve());

result.then(e => {
  console.log("Resolution is complete! Let's party.")
});

Make a chain with promises (waterfall)

myPromise(index, sec) {
  return new Promise((res) => {
    setTimeout(() => { res(`DONE ${index}#`) }, sec)
  }).then((res) => {
    console.log(res)
  })
}  
// Manually created chain 
Promise.resolve()
   .then(() => myPromise(1, 3000))
   .then(() => myPromise(2, 3000))
   .then(() => myPromise(3, 3000))
// Equal to above, created with "reduce"       
const array = [1, 2, 3]
array.reduce(
  // callback
  (accumulator, currentValue, index) => accumulator.then(() => myPromise(index, 3000)), 

  // initValue
  Promise.resolve()
);
// The most advanced way is wrapp all promises in func then check em all
const promises = [
  () => myPromise(1, 3000),
  () => myPromise(2, 3000),
  () => myPromise(3, 3000),
] 

   
const promisesResult = promises.reduce(
  // callback
  (accumulator, currentValue, index) => {
    return accumulator.then(
    	() => currentValue().then((res) => { console.log(res); })
    )
  }, 

  // initValue
  Promise.resolve()
);

promisesResult.then(() => console.log("All done"))
.catch((err) => {  console.log('Error -', log) })

Promise.all vs Promise.allSettled

const promises = [
	Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject('error'),
  Promise.resolve(-100)
];
Promise.all()
(async function() {
  try {
    await Promise.all(promises).then(
      (results) => console.log(results)
    )
  } catch(err) {
    console.log('ERROR:', err) // will get here 
  }
})()
Promise.allSettled()
(async function() {
  try {
    await Promise.allSettled(promises).then(
      (results) => console.log(results)
    )
  } catch(err) {
		console.log('ERROR:', err)
	}
})()

// Output
/* [{ 
  status: "fulfilled",
  value: 1
}, {
  status: "fulfilled",
  value: 2
}, {
  reason: "error",
  status: "rejected"
}, {
  status: "fulfilled",
  value: -100
}] */

Race condition: Function finishes or timeout error

// Simulate a function that resolves after some random time
function performAsyncTask() {
    return new Promise((resolve) => {
        const delay = Math.random() * 5000; // Random delay between 0-5000ms
        console.log(`Async task will take ${delay.toFixed(0)}ms`);
        setTimeout(() => resolve("Async task completed"), delay);
    });
}

// Set a predefined timeout
function timeout(ms) {
    return new Promise((resolve) => {
        setTimeout(() => resolve(`Timeout of ${ms}ms reached`), ms);
    });
}

// Use Promise.race to take the first result
const timeoutDuration = 3000; // 3 seconds

Promise.race([performAsyncTask(), timeout(timeoutDuration)])
    .then((result) => {
        console.log("First action completed:", result);
    })
    .catch((error) => {
        console.error("Error:", error);
    });