async函数返回Promise {<pending>}?

Jak*_*son 7 javascript asynchronous node.js promise

我有以下异步功能:

async function readFile () {
  let content = await new Promise((resolve, reject) => {
    fs.readFile('./file.txt', function (err, content) {
      if (err) {
        return reject(err)
      }
      resolve(content)
    })
  })

  console.log(content)
}

readFile()
Run Code Online (Sandbox Code Playgroud)

这运行得很好.它按预期将文件缓冲区输出到控制台.但现在,如果我尝试返回值:

async function readFile () {
  let content = await new Promise((resolve, reject) => {
    fs.readFile('./file.txt', function (err, content) {
      if (err) {
        return reject(err)
      }
      resolve(content)
    })
  })

  return content
}

console.log(readFile())
Run Code Online (Sandbox Code Playgroud)

我现在得到:

Promise { <pending> }
Run Code Online (Sandbox Code Playgroud)

为什么是这样?为什么你可以在该函数中使用一个值,但是当你从函数中返回它时它现在是一个Promise?

你如何在正常的工作流程中实际使用它?例如,假设我想检查文件是否存在,然后读入文件,然后用内容更新一些数据库,同步伪代码看起来像这样:

if (fileExists(path)) {
  buffer = readFile(path)
  updateDatabase(buffer)
}
Run Code Online (Sandbox Code Playgroud)

该工作流程包含3个单独的异步操作.你会怎么做这样的事情async/await?是否必须将整个脚本包含在async函数中?

async function doSomething () {
  if (fileExists(path)) {
    buffer = readFile(path)
    updateDatabase(buffer)
  }
}
Run Code Online (Sandbox Code Playgroud)

(请记住,这只是伪代码,但希望它能解决我的问题).

Mar*_*lvy 6

所有async函数都返回了注释中提到的promise.因此,您可以readFile像这样重写您的函数:

function readFile() {
  return new Promise((resolve, reject) => {
    fs.readFile('./file.txt', function (err, content) {
      if (err) {
        return reject(err)
      }
      resolve(content)
    })
  })
}
Run Code Online (Sandbox Code Playgroud)

然后,您将使用readFilevia 的返回值await:

console.log(await readFile()) // will log your actual file contents.
Run Code Online (Sandbox Code Playgroud)

这个范例的通常工作流程是将异步操作分解为单独的函数,每个函数返回一个promise,然后在更广泛的async函数中运行它们,就像你建议的那样,但是使用awaits和一些错误处理如下:

async function doSomething () {
  try {  
    const fileCheck = await fileExists(path)

    if (fileCheck) {
      const buffer = await readFile(path)
      await updateDatabase(buffer)
      // Whatever else you want to do
    }
  } catch (err) {
    // handle any rejected Promises here.
  }
}
Run Code Online (Sandbox Code Playgroud)