我有一个简单的节点模块,它连接到数据库,并有几个函数来接收数据,例如这个函数:
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);
}
});
});
}
};
该模块将以这种方式从不同的节点模块调用:
app.js:
import dbCon from './dbConnection.js';
dbCon.getUsers(console.log);
我想使用promises而不是回调来返回数据。到目前为止,我已经阅读了以下线程中的嵌套promises:Writing Clean Code With Nested Promises,但我找不到任何足够简单的解决方案来满足这个用例。使用promise返回result
的正确方式是什么?
发布于 2015-02-10 21:35:47
使用Promise
类
我推荐看一下MDN's Promise docs,它为使用Promise提供了一个很好的起点。或者,我确信有许多在线教程可用。:)
注意:现代浏览器已经支持MDN6的Promise规范(请参阅上面链接的ECMAScript文档),我假设您想要使用本机实现,而不是第三方库。
至于实际的例子..。
基本原理是这样工作的:
resolve
和resolve
。执行逻辑时,您可以调用其中一个函数来满足Promise或拒绝它,并返回错误这可能看起来很多,所以这里有一个实际的示例。
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
})
使用异步/等待语言功能(Node.js >=7.6)
在Node.js 7.6中,v8 JavaScript编译器使用async/await support进行了升级。您现在可以将函数声明为async
,这意味着它们会自动返回一个Promise
,该can在异步函数完成执行时会被解析。在此函数中,可以使用await
关键字等待另一个Promise解析。
下面是一个示例:
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
}
发布于 2015-02-10 21:17:36
使用,您可以使用Promise.promisifyAll
(和Promise.promisify
)将Promise ready方法添加到任何对象。
var Promise = require('bluebird');
// Somewhere around here, the following line is called
Promise.promisifyAll(connection);
exports.getUsersAsync = function () {
return connection.connectAsync()
.then(function () {
return connection.queryAsync('SELECT * FROM Users')
});
};
并像这样使用:
getUsersAsync().then(console.log);
或
// Spread because MySQL queries actually return two resulting arguments,
// which Bluebird resolves as an array.
getUsersAsync().spread(function(rows, fields) {
// Do whatever you want with either rows or fields.
});
添加处理器
蓝鸟支持很多功能,其中之一是处理器,它允许你在Promise.using
和Promise.prototype.disposer
的帮助下安全地处理连接结束后的连接。下面是我的应用程序中的一个示例:
function getConnection(host, user, password, port) {
// connection was already promisified at this point
// The object literal syntax is ES6, it's the equivalent of
// {host: host, user: user, ... }
var connection = mysql.createConnection({host, user, password, port});
return connection.connectAsync()
// connect callback doesn't have arguments. return connection.
.return(connection)
.disposer(function(connection, promise) {
//Disposer is used when Promise.using is finished.
connection.end();
});
}
然后像这样使用它:
exports.getUsersAsync = function () {
return Promise.using(getConnection()).then(function (connection) {
return connection.queryAsync('SELECT * FROM Users')
});
};
一旦promise用值解析(或用Error
拒绝),这将自动结束连接。
发布于 2017-11-15 07:35:50
Node.js版本8.0.0+:
您不再需要使用bluebird来简化node API方法。因为,在8+版本中,您可以使用本机util.promisify
const util = require('util');
const connectAsync = util.promisify(connection.connectAsync);
const queryAsync = util.promisify(connection.queryAsync);
exports.getUsersAsync = function () {
return connectAsync()
.then(function () {
return queryAsync('SELECT * FROM Users')
});
};
现在,不需要使用任何第三方库来执行promisify。
https://stackoverflow.com/questions/28432401
复制相似问题