Kselax.ru

Hacker Kselax – the best hacker in the world

Menu
  • Blog
  • Contacts
  • wp plugin generator
  • English
    • Русский
Menu
promises

How to use promises in JavaScript

Posted on 8 August, 201814 February, 2019 by admin

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

It is used for getting some data from the callback function in some determined function. Promise.all, or .then.

content talbe:

  1. Creating a promise
  2. Using a promise for getting data from two and more callbacks
  3. How to use a promise in a loop
  4. How to handle promise rejection inside async functions

Things that you should remember:

resolve and reject are both return promises, so when you do resolve/reject to interupte the function execution you have to use return resolve or return reject

#Creating a promise

Creating a promise is very simple, we use constructor Promise and inside pass, a callback function with two parameters resolve and reject

The promise should be wrapped in a function. It will work as a closure. Without wrapping we can’t use a promise over a loop, or to pass there some variable that will afterward change by upcoming code. So a simple promise definition should be:

1
2
3
4
5
6
7
8
var my_first_promise = function(){
  return new Promise((resolve, reject) => {
    setTimeout(function(){
      // resolve('Hello world')
      reject('some_error')
    });
  });
};

 

to get a result from a promise we use special functions resolve and reject, where resolve data will be passed to a .then block and reject data will be passed to a .catch

1
2
3
4
5
my_first_promise().then(function(success){
  console.log(`success = ${success}`);
}).catch(function(error){
  console.log(`error = ${error}`);
})

 

#Using a promise for getting data from two and more callbacks

This is a common use case the most frequently used. Assume we have two functions f1 and f2

1
2
3
4
5
6
7
8
9
function f1(fn){
  let ob = {name:'object1'};
  setTimeout(fn, 0, ob);
}
 
function f2(fn){
  let ob = {name:'object2'};
  setTimeout(fn, 0, ob);
}

 

now we can reach each object inside each function one by one

1
2
3
4
5
6
7
f1(function(obj1){
  console.log(obj1.name);
});
 
f2(function(obj2){
  console.log(obj2.name);
});

 

but what shall we do if we want to reach obj1 and obj2 simultaneously? In this case, promises are coming to help us. We have to wrap every callback function to a promise and handle it in some special function Promise.all() that accepts an array of promises.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var pr1 = function(){
  return new Promise((resolve, reject) => {
    f1(function(obj1){
      resolve(obj1);
    })
  })
}
 
var pr2 = function(){
  return new Promise((resolve, reject) => {
    f2(function(obj2){
      resolve(obj2);
    })
  })
}
 
var p1 = pr1();
var p2 = pr2();
 
Promise.all([p1, p2]).then(values => {
  let obj1 = values[0];
  let obj2 = values[1];
  console.log(`obj1.name = ${obj1.name}, obj2.name = ${obj2.name}`); // obj1.name = object1, obj2.name = object2
}).catch(err => {
  console.log(`err = ${err}`);
})

the output
obj1.name = object1, obj2.name = object2

#How to use a promise in a loop?

Yes, we can use promise in the loop, assume we have a contrived task to calculate something in our promises in for and pass to promise counter i. Each promise have to have a unique i. and then we have got results from all promises and output sum. Simple task

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// a function that accepts a callback function
function f(fn){
  let n = 10;
  setTimeout(fn, 0, n);
}
 
// a promise function
function pr(i){
  return new Promise((resolve, reject) => {
    f(function(n){
      // console.log(`i = ${i}`);
      resolve(i * n);
    })
  })
}
 
let prs = [];
for (let i = 0; i < 10; i++){
  prs.push(pr(i));
}
 
Promise.all(prs).then(values => {
  console.log(values); // [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 ]
  let sum = 0;
  for(let i = 0, max = values.length; i < max; i++){
    sum += values[i];
  }
  console.log(`sum = ${sum}`); // 450
}).catch(err => {
  console.log(`err = ${err}`);
})

 

as you see promises successfully helped us to solve such a difficult task.

 

#How to handle promise rejection inside async functions

Case 1 The handle promise inside an async function.

We can handle such a promise by using try/catch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// the f2 async function doesn't has a catch handler
// that allows users to specify own catch to handle
const f2 = async () => {
  return new Promise((resolve, reject) => {
    reject('reject f2')
  })
}
 
const f1 = async () => {
  const pr = () => {
    return new Promise( async (resolve, reject) => {
      reject("reject pr")
    })
    .catch(e => {
      console.log('caught 1');
    })
  }
 
try {
  await pr()
  await f2() // without await the try catch will not work
} catch(e) {
  console.log('caught from try');
}
  
  console.log('here we are');
}
 
f1()

Important: the libraries like puppeteer doesn’t has in their async functions API catch handlers. You have to do like this

1
2
3
4
5
6
7
try {
  const page2 = await browser.newPage()
  await page2.goto(url2)
  await page2.waitFor('selector: div.column-search-panel__center > input')
} catch(e) {
  console.log('caught');
}

when you specify your own promise inside an async function you have to add try catch there too

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const getData = async (number, accreditation) => {
  try {
    const browser = await puppeteer.launch({
      headless: false,
      slowMo: 250
    })
    const pr1 = () => {
      return new Promise( async(resolve, reject) => {
        // here should be try catch block
        // without here will be unhandled rejections
        // because of puppeteer functions is an async
        // and when they will rejected nothing will
        // handle them (or you have to attach .catch)
        try {
          const page2 = await browser.newPage()
          await page2.goto(url2)
          await page2.waitFor('selector: div.column-search-panel__center > input')
        } catch(e) {
          console.log('caught');
        }
      })
    }
 
    await pr1()
  } catch (e) {
    console.log('caught');
  }
}

so always use try/catch especially with third party libs

 

#How to use Promise.race properly

Promise.race allows us to put on waiting a few promises and return the result of one the first.
we use it often with puppeteer when we need to know what the DOM state is Here is an example from puppeteer how to wait for needed selector. The example below show how it works. You have to change setTimeout time to allow promises either pr1 or pr2 to be the first. The less time the first promise.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const pr1 = () => {
  return new Promise(async (resolve, reject) => {
    setTimeout(() => {
      resolve('[resolve]')
    }, 1000)
  })
}
 
const pr2 = () => {
  return new Promise(async (resolve, reject) => {
    setTimeout(() => {
      reject('[reject]')
    }, 2000)
  })
}
 
const getData = async () => {
  try {
    // Promise.race allows one the first promise resolve or reject
    const res = await Promise.race([
      pr1(),
      pr2()
    ]).catch(e => {
      // this is code will run when the first promise is rejected
      // without this block the execution will be passed to the
      // try/catch
      console.log('[caught reject]');
      return e
    })
 
    console.log('res = ', res);
 
    console.log('here we are');
  } catch(e) {
    console.log('e = ', e);
  }
}
 
getData()

 

the end

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • bash (1)
  • English (9)
  • JavaScript (4)
  • node.js (22)
  • photoshop (1)
  • php (3)
  • React (9)
  • sclerotic (6)
  • Ubuntu (10)
  • Uncategorized (13)
  • Wordpress (1)

Tags

Ajax apache2 automation bash chrome-extension command line editor ejs email English English-grammar framework functions git graphql handlebars hybrid app installation javascript js linux newbie node.js node.js javascript nodemailer npm objects Performance php phpmyadmin playonlinux promise rabbitmq React react-router redis reverse-proxy session shell socket.io sublime text 3 time zones ubuntu unity webpack

Recent Comments

  • damien on How to install npm and nodejs the latest versions on ubuntu
  • Cam on How to install npm and nodejs the latest versions on ubuntu
  • Pierre on socket.io with apache as a reverse proxy on the CentOS
  • admin on How to use react-router with a few languages
  • admin on How to install npm and nodejs the latest versions on ubuntu
©2021 Kselax.ru Theme by ThemeGiant