nodejs-在函数内执行多个异步调用的最佳方法?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nodejs-在函数内执行多个异步调用的最佳方法?相关的知识,希望对你有一定的参考价值。

我正在使用Express JS(Express 4)框架创建API。我对NodeJS很陌生,所以我想知道在同一个函数中执行多个异步调用的最佳方法。

对于这个例子,我在登录控制器中有一个名为Login的函数。在这个函数中,假设我要做一些异步调用来验证用户,保存登录信息和类似的功能。

但对于某些异步调用,要处理的数据应该从之前的异步调用中获取(它们是依赖函数),而某些函数则不是这样。

现在,这就是我打电话的方式。

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 Chaining

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)这个策略也使用promises。在我看来,它提高了可读性,因为您将每个单独的promise调用重构为单独的方法。

Codepen

// 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);
  })

以上是关于nodejs-在函数内执行多个异步调用的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

nodejs知识结构

nodejs所用的概念(同步,异步,事件驱动,事件循环等)通俗解释

Java 异步编程最佳实践

如何在多个异步调用中向 NodeJS 中的数据库发送响应?

在地图中调用异步函数的最佳方法?

File-nodejs