使用nodeAPI時遇到非同步問題的解決方法

大雄45發表於2023-03-03
導讀 這篇文章主要為大家介紹了使用nodeAPI時遇到過非同步問題解決,有需要的朋友可以借鑑參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
問題

閒逛技術群時常常看到群友遇到非同步問題, 這裡就最近看到的問題做個解答:

問題大致是這樣:

下面這段程式碼, 是希望輸出456的, 但實際上卻輸出了[], 因為readFile的回撥會等到檔案讀取完成才會執行, readFile不會阻塞程式碼執行, 因此return demo會先執行, 此時demo值為[].

const fs = require('fs')
const readFileFn = () => {
    let demo = []
  fs.readFile('./config.json', async function (err, date) {
    Promise.all([Promise.resolve(() => 456)]).then(res => {
      demo = res
    })
  })
  return demo
}
console.log('end', readFileFn()) // 要輸出456

很典型的非同步問題, 解決方法也由不少, 我們來探討一下:

既然readFile提供回撥函式來執行讀完檔案後的操作, 我們同樣可以提供回撥函式來執行readFile結束後的操作:

const fs = require('fs')
const readFileFn = (callback) => {
  fs.readFile('./config.json', async function (err, date) {
    Promise.all([Promise.resolve(456)]).then(res => {
      callback(res)
    })
  })
}
readFileFn(data => console.log(data)) // [ 456 ]

現代JS程式設計似乎更傾向於Promise風格, 同時我們結合async/await可以進一步簡化程式碼

const fs = require('fs')
const readFileFn = async () => {
  const [result] = await Promise.all([
    new Promise(resolve => fs.readFile('./config.json', (err, data) => resolve(456))),
  ])
  return result
}
readFileFn().then(res => console.log(res)) // 456

這裡我們建立了一個Promise, 在readFile的回撥函式執行時我們resolve它, 這時Promise才算結束

我們還可以之間讓readFileFn返回一個Promise

const readFileFn = () => {
  return new Promise(resolve => {
    fs.readFile('./config.json', async function (err, date) {
      Promise.all([Promise.resolve(456)]).then(res => {
        resolve(res)
      })
    })
  })
}
readFileFn().then(console.log) // [456]
// readFileFn().then(res => console.log(res))
總結

在node中有很多類似於readFile的API, 他們採用回撥函式的方式實現非同步, 因為在以前, 回撥函式被用來實現非同步, 之後出現了諸如Promise, async/await這樣的非同步方案,現代的JS程式設計,更加鼓勵使用新方案,他們完全可以和以前的回撥函式方案相容。

原文來自:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2937988/,如需轉載,請註明出處,否則將追究法律責任。

相關文章