Converting callbacks to promises

Nói đến promises và callbacks thì tôi nghĩ bay giờ ai cũng biết về hai khái niệm này rồi. Nhưng khổ một nỗi là sử dụng Promises (or async/await) quen rồi nên khi gặp lại callbacks cảm thấy không sướng chút nào? Vì thật dễ dàng khi sử dụng promises so với callbacks. Nhưng rất tiếc khi các bạn nào làm nhiều ở Node thì đa số các API của Node vẫn còn đang xài callbacks, vậy làm sao chuyển callbacks qua promises. Hôm nay, mình sẽ show cho anh em devjs convert callbacks to promises.

Đọc thêm về : Series về Promises và Async/Await 

#Đầu tiên mình sẽ lấy một API của Node làm ví dụ.

Ví dụ readFile in Node 12.11.1 Cú pháp:

 fs.readFile(path[, options], callback)
 

Sử dụng như thế này

 fs.readFile('/etc/passwd', (err, data) => {
  if (err) throw err;
  console.log(data);
})

Nếu một ngày nào đó bạn gặp trường hợp này thì bạn vẫn có thể sử dụng util.promisify để convert từ callbacks qua promises như code dưới đây:

const fs = require('fs')
const util = require('util')

const readFilePromise = util.promisify(fs.readFile)

Từ đó chúng ta có thể sử dụng như bất kỳ promises nào;

readFilePromise(filePath, options)
  .then(data => {/* Do something with data */})
  .catch(err => {/* Handle error */}

Có khi lúc bạn không thể sử dụng util.promisify thì bạn vẫn có thể viết một function return về một promises của mình. Ví dụ:

const readFilePromise = () => {
  return new Promise ((resolve, reject) => {
    // ...  
  })
}

Code đầy đủ hơn và show cho các bạn thấy nó cũng dễ dàng hơn

const readFilePromise = () => {
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, options, (err, data) => {
      if (err) return reject(err)
      resolve(data)
    })
  })
}

Sử dụng thì cũng không khác gì phương án trên

 readFilePromise(filePath, options)
  .then(data => {/* Do something with data */})
  .catch(err => {/* Handle error */}
  

Thật ra không có gì phải suy nghĩ ngoài vấn đề này. Đó là việc resolve chỉ pass được một argument, vậy có những trường hợp cần pass multiple arguments thì phải làm thế nào. Nói vậy thôi chứ dễ như code vậy. Mình sẽ lấy ví dụ trên để viết thêm và giải thích cho anh em xem thêm Tôi thêm một object trả về trong resolve như thế này.

const readFilePromise = () => {
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, options, (err, data, data1) => {
      if (err) return reject(err)
      resolve(data, data1) ;// bạn không thể viết như thế này được 
    })
  })
}

Mà bạn phải sử dụng Array or Object như:

resolve([data, data1])
or
resolve({data, data1}) 

Và sử dụng bình thường như một promises.

// If you use arrays
readFilePromise(options)
  .then([data, data1]) => {/* Do something */})

// If you use objects
readFilePromise(options)
  .then({data, data1}) => {/* Do something */})

Thật ra đây một bài viết giúp các bạn mới hiểu về promises và chưa biết cách sử dụng chúng. Nếu các bạn thấy có giúp gì được cho bạn, thì đừng ngại hãy Share cho những người như các bạn nhoé. 

Đọc thêm về : Series về Promises và Async/Await

Có nhiều cách các bạn có thể tham khảo sau khi đọc bài viết này : 

https://stackoverflow.com/questions/34628305/using-promises-with-fs-readfile-in-a-loop 

Ref: zellwk