nodejs-在函数内执行多个异步调用的最佳方法?
nodejs- Best method to perform multiple async calls inside a function?
我正在使用 Express JS (Express 4) 框架创建 API。我是 NodeJS 的新手,所以我想知道在同一函数内执行多个异步调用的最佳方法。
对于这个例子,我的登录控制器中有一个名为登录的函数。在这个函数中,假设我必须进行相当多的异步调用来验证用户身份、保存登录信息和类似的功能。
但是对于一些异步调用,要处理的数据应该从之前的异步调用中获取(它们是依赖函数),有些函数不是这样。
现在,这就是我打电话的方式。
exports.login = function (req, res) {
var user = {
email: 'fakeemail@id.com',
password: 'password'
};
//Async call 1
Login.authUser(user, function (err1, rows1) {
var user_id = rows1[0].id;
//Async call 2 (depends on async call 1 for user_id)
Login.fetchUserDetails(user_id, function (err2, rows2) {
//Async call 3
Login.updateLoginInfo(param3, function (err3, rows3) {
//Some functionality occurs here then async call 4 happens
//Async call 4
Login.someOtherFunctionality(param4, function (err4, rows4) {
//return response to user
res.json({
success: true
});
});
});
});
});
};
现在所有这些异步调用都是嵌套的。我还有其他方法可以做到这一点吗?
P.S: 我没有在这个例子中添加错误处理
您也可以使用 promise。它会让你的语法更漂亮。你的代码看起来像
Login.authUser(user).
then(fetchUser).
then(updateLoginInfo).
then(someOtherFunctionality).
catch(function(error){
//log your error or whatever
});
您可以按照 Shahzeb 的建议使用 Promise
。
Promises
是将来(异步)解析的对象。一旦 Promise
完成,它要么解决要么拒绝。所有已解决的承诺都是 then
ed,那些被拒绝的是 catch
ed
伪代码
let myPromise = function() {
return new Promise(function(resolve, reject) {
resolve('foo');
});
};
myPromise().then( (v) => {
console.log(v);
})
使用 Promise 链
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
更多详情参考Promise Chaining and
使用async/await(需要Node.js v7.6)
该策略也使用承诺。在我看来,它提高了可读性,因为您将每个单独的承诺调用重构为单独的方法。
// mock async calls
const authUser = user => Promise.resolve([{ id: 1 }]); // returns users id
const fetchUserDetails = user_id => Promise.resolve({ name: 'Fred', age: '10000' }); // returns users details
const updateLoginInfo = param3 => Promise.resolve({ status: 'success' }); // returns success?
const someOtherFunctionality = param3 => Promise.resolve({ field: 'value' }); // returns something
// all async functions return a promise
const login = async (/*req, res*/) => {
// User object
const user = {
email: 'fakeemail@id.com',
password: 'password'
};
// Async call 1
console.log(`Authorizing user...`);
const rows1 = await authUser(user);
const user_id = rows1[0].id;
console.log(`User ${user_id} authorized.`);
// Async call 2 (depends on async call 1 for user_id)
console.log(`Fetching user detail...`);
const rows2 = await fetchUserDetails(user_id);
console.log(`User Detail was fetched: ${JSON.stringify(rows2)}`);
// Async call 3
console.log(`Updating login info...`);
const param3 = `something`;
const rows3 = await updateLoginInfo(param3);
console.log(`Login info was successful: ${JSON.stringify(rows3)}`);
// Some functionality occurs here then async call 4 happens
console.log(`\nDoing stuff after async call 3, but before async call 4....\n`);
// Async call 4
console.log(`Async call 4...`);
const param4 = `something`;
const rows4 = await someOtherFunctionality(param4);
console.log(`END OF LOGIN FUNCTION`);
return 'returned value';
}
// run the async function
login()
.then(result => {
// respond
// res.json({ success: true });
console.log(`Promise value: ${result}`);
console.log(`Response: { success: true }`);
})
.catch(err => {
console.log(err);
})
我正在使用 Express JS (Express 4) 框架创建 API。我是 NodeJS 的新手,所以我想知道在同一函数内执行多个异步调用的最佳方法。
对于这个例子,我的登录控制器中有一个名为登录的函数。在这个函数中,假设我必须进行相当多的异步调用来验证用户身份、保存登录信息和类似的功能。
但是对于一些异步调用,要处理的数据应该从之前的异步调用中获取(它们是依赖函数),有些函数不是这样。
现在,这就是我打电话的方式。
exports.login = function (req, res) {
var user = {
email: 'fakeemail@id.com',
password: 'password'
};
//Async call 1
Login.authUser(user, function (err1, rows1) {
var user_id = rows1[0].id;
//Async call 2 (depends on async call 1 for user_id)
Login.fetchUserDetails(user_id, function (err2, rows2) {
//Async call 3
Login.updateLoginInfo(param3, function (err3, rows3) {
//Some functionality occurs here then async call 4 happens
//Async call 4
Login.someOtherFunctionality(param4, function (err4, rows4) {
//return response to user
res.json({
success: true
});
});
});
});
});
};
现在所有这些异步调用都是嵌套的。我还有其他方法可以做到这一点吗?
P.S: 我没有在这个例子中添加错误处理
您也可以使用 promise。它会让你的语法更漂亮。你的代码看起来像
Login.authUser(user).
then(fetchUser).
then(updateLoginInfo).
then(someOtherFunctionality).
catch(function(error){
//log your error or whatever
});
您可以按照 Shahzeb 的建议使用 Promise
。
Promises
是将来(异步)解析的对象。一旦 Promise
完成,它要么解决要么拒绝。所有已解决的承诺都是 then
ed,那些被拒绝的是 catch
ed
伪代码
let myPromise = function() {
return new Promise(function(resolve, reject) {
resolve('foo');
});
};
myPromise().then( (v) => {
console.log(v);
})
使用 Promise 链
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
使用async/await(需要Node.js v7.6) 该策略也使用承诺。在我看来,它提高了可读性,因为您将每个单独的承诺调用重构为单独的方法。
// mock async calls
const authUser = user => Promise.resolve([{ id: 1 }]); // returns users id
const fetchUserDetails = user_id => Promise.resolve({ name: 'Fred', age: '10000' }); // returns users details
const updateLoginInfo = param3 => Promise.resolve({ status: 'success' }); // returns success?
const someOtherFunctionality = param3 => Promise.resolve({ field: 'value' }); // returns something
// all async functions return a promise
const login = async (/*req, res*/) => {
// User object
const user = {
email: 'fakeemail@id.com',
password: 'password'
};
// Async call 1
console.log(`Authorizing user...`);
const rows1 = await authUser(user);
const user_id = rows1[0].id;
console.log(`User ${user_id} authorized.`);
// Async call 2 (depends on async call 1 for user_id)
console.log(`Fetching user detail...`);
const rows2 = await fetchUserDetails(user_id);
console.log(`User Detail was fetched: ${JSON.stringify(rows2)}`);
// Async call 3
console.log(`Updating login info...`);
const param3 = `something`;
const rows3 = await updateLoginInfo(param3);
console.log(`Login info was successful: ${JSON.stringify(rows3)}`);
// Some functionality occurs here then async call 4 happens
console.log(`\nDoing stuff after async call 3, but before async call 4....\n`);
// Async call 4
console.log(`Async call 4...`);
const param4 = `something`;
const rows4 = await someOtherFunctionality(param4);
console.log(`END OF LOGIN FUNCTION`);
return 'returned value';
}
// run the async function
login()
.then(result => {
// respond
// res.json({ success: true });
console.log(`Promise value: ${result}`);
console.log(`Response: { success: true }`);
})
.catch(err => {
console.log(err);
})