在 Node.js 中用 promise 替换回调 [英] Replacing callbacks with promises in Node.js
问题描述
我有一个简单的节点模块,它连接到数据库并有几个接收数据的函数,例如这个函数:
I have a simple node module which connects to a database and has several functions to receive data, for example this function:
dbConnection.js:
import mysql from 'mysql';
const connection = mysql.createConnection({
host: 'localhost',
user: 'user',
password: 'password',
database: 'db'
});
export default {
getUsers(callback) {
connection.connect(() => {
connection.query('SELECT * FROM Users', (err, result) => {
if (!err){
callback(result);
}
});
});
}
};
该模块将从不同的节点模块以这种方式调用:
The module would be called this way from a different node module:
app.js:
import dbCon from './dbConnection.js';
dbCon.getUsers(console.log);
我想使用承诺而不是回调来返回数据.到目前为止,我已经在以下线程中阅读了嵌套承诺:Writing Clean Code With Nested Promises,但我找不到任何对这个用例来说足够简单的解决方案.使用承诺返回 result
的正确方法是什么?
I would like to use promises instead of callbacks in order to return the data.
So far I've read about nested promises in the following thread: Writing Clean Code With Nested Promises, but I couldn't find any solution that is simple enough for this use case.
What would be the correct way to return result
using a promise?
推荐答案
使用 Promise
类
我建议查看 MDN 的 Promise 文档 为使用 Promise 提供了一个很好的起点.或者,我相信网上有很多教程.:)
Using the Promise
class
I recommend to take a look at MDN's Promise docs which offer a good starting point for using Promises. Alternatively, I am sure there are many tutorials available online.:)
注意:现代浏览器已经支持 Promise 的 ECMAScript 6 规范(请参阅上面链接的 MDN 文档),我假设您想使用本机实现,而无需 3rd 方库.
Note: Modern browsers already support ECMAScript 6 specification of Promises (see the MDN docs linked above) and I assume that you want to use the native implementation, without 3rd party libraries.
至于一个实际例子...
As for an actual example...
基本原理如下:
- 您的 API 被调用
- 你创建了一个新的 Promise 对象,这个对象接受一个函数作为构造函数参数
- 您提供的函数由底层实现调用,该函数被赋予两个函数 -
resolve
和reject
- 完成逻辑后,您可以调用其中之一来完成 Promise 或以错误拒绝它
这可能看起来很多,所以这里是一个实际例子.
This might seem like a lot so here is an actual example.
exports.getUsers = function getUsers () {
// Return the Promise right away, unless you really need to
// do something before you create a new Promise, but usually
// this can go into the function below
return new Promise((resolve, reject) => {
// reject and resolve are functions provided by the Promise
// implementation. Call only one of them.
// Do your logic here - you can do WTF you want.:)
connection.query('SELECT * FROM Users', (err, result) => {
// PS. Fail fast! Handle errors first, then move to the
// important stuff (that's a good practice at least)
if (err) {
// Reject the Promise with an error
return reject(err)
}
// Resolve (or fulfill) the promise with data
return resolve(result)
})
})
}
// Usage:
exports.getUsers() // Returns a Promise!
.then(users => {
// Do stuff with users
})
.catch(err => {
// handle errors
})
使用 async/await 语言功能 (Node.js >=7.6)
在 Node.js 7.6 中,v8 JavaScript 编译器升级为 异步/等待支持.您现在可以将函数声明为 async
,这意味着它们会自动返回一个 Promise
,当异步函数完成执行时,该函数会被解析.在这个函数中,你可以使用 await
关键字来等待另一个 Promise 解析.
Using the async/await language feature (Node.js >=7.6)
In Node.js 7.6, the v8 JavaScript compiler was upgraded with async/await support. You can now declare functions as being async
, which means they automatically return a Promise
which is resolved when the async function completes execution. Inside this function, you can use the await
keyword to wait until another Promise resolves.
这是一个例子:
exports.getUsers = async function getUsers() {
// We are in an async function - this will return Promise
// no matter what.
// We can interact with other functions which return a
// Promise very easily:
const result = await connection.query('select * from users')
// Interacting with callback-based APIs is a bit more
// complicated but still very easy:
const result2 = await new Promise((resolve, reject) => {
connection.query('select * from users', (err, res) => {
return void err ? reject(err) : resolve(res)
})
})
// Returning a value will cause the promise to be resolved
// with that value
return result
}
这篇关于在 Node.js 中用 promise 替换回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!