美文网首页
异步函数vs返回promise的函数

异步函数vs返回promise的函数

作者: 范小饭_ | 来源:发表于2019-11-17 20:01 被阅读0次

Async function vs. a function that returns a Promise
翻译:范小饭

仅返回Promise的函数与使用async关键字声明的函数之间存在很小但非常重要的区别。

看一下以下代码片段:

function fn(obj) {
  const someProp = obj.someProp
  return Promise.resolve(someProp)
}

async function asyncFn(obj) {
  const someProp = obj.someProp
  return Promise.resolve(someProp)
}

asyncFn().catch(err => console.error('Catched')) // => 'Catched'
fn().catch(err => console.error('Catched')) // => TypeError: Cannot read property 'someProp' of undefined

正如你看见的,以上两个函数有相同的函数体,我们试图在函数里访问argument,但是实际上2个argument都是undefined,两个函数唯一不同的是,asyncFn函数被关键字async声明为异步函数

这意味着js将会确定asyncFn函数将会返回一个promise(无论是resolved还是rejected),即使函数体里发生了错误,在我们的案例中是.catch代码块。

然而,引擎不知道fn函数也返回一个promise,因此它不会调用catch()

A more real-world version

我知道你现在正在想什么:

我什么时候会犯这样的错误?

对吗?

让我们写一个像刚才那样简单的应用。

假设我们有一个使用MongoDB的Express应用程序。如果你相信我,我已经把代码放在了this github repo
,所以你可以clone下来,然后在本地运行,但是我也会把代码粘贴在下面:

app.js

// app.js
'use strict'

const express = require('express')
const db = require('./db')

const userModel = require('./models/user-model')
const app = express()

db.connect()

app.get('/users/:id', (req, res) => {
  return userModel
    .getUserById(req.params.id)
    .then(user => res.json(user))
    .catch(err => res.status(400).json({ error: 'An error occured' }))
})

app.listen(3000, () => console.log('Server is listening'))

仔细看,.catch代码块在route中定义了,这个地方会有魔术发生。

db.js 被用来链接mongo数据库和获取mongobd连接:

'use strict'

const MongoClient = require('mongodb').MongoClient

const url = 'mongodb://localhost:27017'
const dbName = 'async-promise-test'

const client = new MongoClient(url)

let db

module.exports = {
  connect() {
    return new Promise((resolve, reject) => {
      client.connect(err => {
        if (err) return reject(err)
        console.log('Connected successfully to server')

        db = client.db(dbName)
        resolve(db)
      })
    })
  },
  getDb() {
    return db
  }
}

最后,我们看我的user模块,只有一个getUserById函数:

// models/user-model.js
'use strict'

const ObjectId = require('mongodb').ObjectId
const db = require('../db')

const collectionName = 'users'

module.exports = {
  /**
   * Get's a user by it's ID
   * @param {string} id The id of the user
   * @returns {Promise<Object>} The user object
   */
  getUserById(id) {
    return db
      .getDb()
      .collection(collectionName)
      .findOne({ _id: new ObjectId(id) })
  }
}

如果您回头查看app.js文件,你会发现访问url:localhost:3000/users/<id>时会调用getUserById,

当你访问localhost:3000/users/1.你觉得会发生什么?

好吧,如果您回答:“我将从mongo那里收到一个巨大的错误”-您是对的。确切地说,您会收到如下错误:

Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters

您怎么看,这个.catch块会被调用吗?

// app.js

// ... stuff ...

app.get('/users/:id', (req, res) => {
  return userModel
    .getUserById(req.params.id)
    .then(user => res.json(user))
    .catch(err => res.status(400).json({ error: 'An error occured' })) // <=== THIS ONE HERE!
})

// ... stuff ...

没有

丝毫没有

如果将函数声明更改为此,会发生什么?

module.exports = {
  // Note that async keyword right there!
  async findById(id) {
    return db
      .getDb()
      .collection(collectionName)
      .findOne({ _id: new ObjectId(id) })
  }
}

是的,您已经掌握了一切。我们的.catch()块将被调用,并且我们将以一个不错的json错误响应用户。

我希望对于您中的某些人来说,这些信息是新的。注意:这篇文章中我没有试图让你总是用async函数,尽管它们非常酷。他们有用例,但仍然只是Promises上的语法糖。

我只是想让您知道,有时候这些问题可能会花很多时间,当您遇到上述错误时,您可能知道问题的出处。

相关文章

  • 异步函数vs返回promise的函数

    Async function vs. a function that returns a Promise翻译:范小...

  • 【Dart】异步函数

    异步函数 JavaScript中,异步调用通过Promise来实现async函数返回一个Promise。await...

  • async await

    async 返回的是一个promise await 后面跟的函数,函数必须返回的是一个promise对象(异步情况...

  • 使用Promise实例 获取模拟数据

    1.定义函数getListJson函数返回一个封装了异步操作的Promise实例Promise接受一个函数作为参数...

  • GCD学习记录

    同步 vs. 异步同步函数在任务完成后才会将控制权返回给调用者。异步函数会立即返回,不会等待任务完成。因此异步函数...

  • 2020-04-15 async 函数

    async 函数 异步操作函数 1.基本用法 async函数返回一个 Promise 对象,可以使用then方法添...

  • Async/await

    原文 acync 让异步函数看起来像同步函数,返回一个promise对象 await 只能在acync函数中使用,...

  • nodejs--day4笔记

    1. 同步与异步API 回调函数 通过回调函数返回异步API的值 代码执行顺序 2. promise 解决回调...

  • ES6 - async await

    async 是什么 async 用于声明一个异步函数,这个函数 return 的内容如果是 promise,则返回...

  • 循环多个 Promise 异步函数

    了解Promise 循环多个 Promise 异步函数

网友评论

      本文标题:异步函数vs返回promise的函数

      本文链接:https://www.haomeiwen.com/subject/nefmictx.html