如何将回调代码转换为异步/等待?

时间:2018-02-02 05:28:34

标签: javascript node.js mongodb asynchronous mongoose

我正在基于节点快速的Web应用程序中使用 Mongoose ODM 来处理 MongoDB ,该应用程序以回调方式提供其API。这种方式创建了一个回调地狱来填充文档。

编辑1:我添加了当前的工作代码。

User.remove({}, (err) => {
  if (err) return console.error(err)

  let admin = new User({
    email: 'admin@dap.com',
    password: 'dapdap'
  })

  admin.save((err, admin) => {
    if (err) return console.error(err)

    console.info('Success')
    mongoose.disconnect()
  })

})

是否有一种优雅的方法可以将回调转换为javascript中的async / await方式?在猫鼬环境中?

6 个答案:

答案 0 :(得分:0)

你能配置mongoose来使用蓝鸟吗?

mongoose.Promise = require('bluebird');

然后你可以想象并做:

User.remove().then(() => {
    let admin = new User({ ... });

    admin.save().then((admin) => {

    }).catch((err) => {
      //Saving admin error handling
    });
}).catch((err) {
  //User remove error handling
});

答案 1 :(得分:0)

您在上面写的相同代码可以写成承诺。来自原始文档,

" Mongoose查询不是承诺。但是,它们对yield和async / await都有.then()函数。如果您需要完全成熟的承诺,请使用.exec()函数。"

因此,您可以使用async await模式,如下所示,

async function removeUser () {
    // Surround the following call with a try catch
    await User.remove({});
}

编辑:

这里的一个答案是关于插入蓝鸟的承诺。虽然这是一个很好的方法,但它是可选的。您可以在不插入自己的Promise库的情况下执行相同的操作。

答案 2 :(得分:0)

你可以使用Promise:

const userRemovePromise = new Promise((resolve, reject) => {
    User.remove({}, (err) => {
      if (err) reject();

      let admin = new User({
        email: 'admin@dap.com',
        password: 'dapdap'
      })

      admin.save((err, admin) => {
        if (err) reject();

        resolve();
      })

    });

});

userRemovePromise.then(function(){  
    mongoose.disconnect();
});

答案 3 :(得分:0)

由于mongoose的默认承诺库mpromise现已弃用,因此您可以插入自己的promise库以使mongoose的操作与await / async一起使用。

Mongoose查询不是承诺。但是,它们对yield和async / await都有.then()函数。如果您需要完全成熟的承诺,请使用.exec()函数。

mongoose.Promise = require('bluebird'); bluebird promise
// mongoose.Promise = global.Promise; // default js promise - 4x- time slower than bluebird

async function removeUser () {
  try {
    await User.remove({}).exec();
    let admin = new User({
      email: 'admin@dap.com',
      password: 'dapdap'
    })
    await admin.save();
    } catch (e) {
        console.log(e);
    }
}

官方文件:mongoosejs.com/docs/promises.html

答案 4 :(得分:0)

Mongoose的最新版本返回Promise以及提供常规回调样式模式。由于async函数是Promises的合成糖,因此您可以await调用Mongoose方法。

async function clearUsers () {
  try {
    await User.remove({})
    let admin = new User({
      email: 'admin@dap.com',
      password: 'dapdap'
    })
    await admin.save()
    console.info('Success')
    mongoose.disconnect()
  } catch (e) {
    console.error(e)
  }
}

要记住的一些事情:

  • async函数始终返回Promise。如果你没有从async函数返回任何内容,它仍将返回一个Promise,它在该函数执行完成时解析,但不会以任何值解析。
  • try/catch函数中的
  • async与常规同步代码的工作方式相同。如果在try正文throw任何函数调用或返回拒绝的承诺,则执行会在该行停止并继续执行{{ 1}} body。
  • 拒绝承诺“涓流”函数调用链。这意味着最顶层的被调用者可以处理错误。请参阅以下示例:

这是一种应该避免的反模式,除非你绝对需要处理特定函数中的错误,可能是为了从不同的来源提供返回值:

catch

上面的内容可能会像下面这样实现,但仍会捕获错误,不会导致运行时出现混乱/崩溃:

async function fn1 () {
  throw new Error("Something went wrong")
}

async function fn2 () {
  try {
    await fn1()
  } catch (e) {
    throw e
  }
}

async function fn3 () {
  try {
    await fn2()
  } catch (e) {
    throw e
  }
}

async function run () {
  try {
    await fn3()
  } catch (e) {
    console.error(e)
  }
}

多种方式来编写上述代码,这些代码都是有效的,所以我建议您探索这些代码。

记住上面的例子,你的函数async function fn1 () { throw new Error("Something went wrong") } function fn2 () { return fn1() } function fn3 () { return fn2() } async function run () { try { await fn3() } catch (e) { console.error(e) } } 可以改写为:

clearUsers()

然后可能以两种不同的方式呼叫;

通过直接与Promise交互:

async function clearUsers () {
  await User.remove({})
  let admin = new User({
    email: 'admin@dap.com',
    password: 'dapdap'
  })
  await admin.save()
  mongoose.disconnect()
}

或来自另一个异步函数:

clearUsers()
  .then(() => {
    console.log('Success')
  })
  .catch((e) => {
    console.error(e)
  })

如果(async function () { try { await clearUsers() console.log('Success') } catch (e) { console.error(e) } })() 函数中的任何函数调用,例如clearUsers(),执行将在该行停止并返回被拒绝的承诺这将在两个变体中的相应await admin.save()块中捕获。

答案 5 :(得分:-2)

使用Bluebird是处理promises中回调的一个很好的选择,它使得在某种程度上更容易理解。

但我会建议你试试

Async.js

它专门用于管理javascript的异步特性。

图书馆的{p> This particular function会完全按照您的意愿行事。