【问题标题】:Use callback or promise to make async code to work like sync in nodejs使用回调或承诺使异步代码像 nodejs 中的同步一样工作
【发布时间】:2018-12-02 12:45:33
【问题描述】:

我的nodejs api函数:

exports.userSignup = (req, res) => {
  const home = {
    address: req.body.name,
    phoneno: req.body.code,
  };
  Home.create(home)
    .then((data) => {
      createUser()
        // i want to complete the above createUser() function fully then only i need to move to this below then function

        .then(() => {
          const loginDetails = {
            username: 'stackoverflow',
          };
          User.create(loginDetails)
            .then((data) => {
              return res.status(200).send(data);
            }).catch((err) => {
              console.log('error while create schema:', err);
            });
        });

    })
    .catch((err) => {
      console.log('err:', err);
    });
};

我的createUser函数代码:

const createUser = () => {
  Home.findAll({
    raw: true,
  }).then((data) => {
    data.forEach((client) => {
      postgresDB.createSchema(client.code).then(() => {
        Object.keys(postgresDB.models).forEach((currentItem) => {
          postgresDB.models[currentItem].schema(client.code).sync();
        });
        console.log('Postgres schema created');
      }).catch((err) => {
        console.log(err);
      });
    });
  }).catch((err) => {
    console.log('Warning:', err.message);
  });
};
createUser();

但是这个是异步的,

如何使用 Promise 解决拒绝或回调?

查看我的代码,我做了一个需要先工作的评论,

我尝试了异步等待但不工作!

【问题讨论】:

  • 更新了我的答案。没有注意到您正在 for 循环中执行异步函数调用。片段应该可以工作。
  • 没有异步代码会同步工作。您需要调整您的 forEach 循环

标签: javascript node.js asynchronous callback promise


【解决方案1】:

您可以在 createUser 函数中使用 async 和 await。您可以通过使用 promise 来更改您的功能,我们可以解决或拒绝。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

【讨论】:

  • 我试过这个,现在也是下面api中的代码,首先工作! createUser 函数尚未完成,但导出 api 函数“then”函数正在工作。
  • 这个例子在很多层面上都是错误的。最大的问题是,由于forEach() 没有返回承诺,await forEach(fn) 实际上在fn 完成之前不会暂停,请参阅thecodebarbarian.com/…。此外,await fn().then(async() => { foo(); }); 是一个可怕的反模式,它消除了使用 async/await 的任何可读性优势。使用await fn(); foo();
  • @vkarpov15,谢谢。其实我犯了一个错误。 forEach 实际上在 fn 完成之前不会暂停,因为 forEach 已经是一个异步函数。
【解决方案2】:

如果async/await 不适合您,只需使用承诺链。看到人们只是用 Promise 编写基于回调的代码,却忘记了你可以通过从 onFulfilled() 参数返回一个 Promise 到 then() 来链接 Promise,真是太痛苦了:

const createUser = () => {
  return Home.findAll({ raw: true }).
    then(data => {
      return Promise.all(data.map(client => postgresDB.createSchema(client.code)));
    }).
    then(() => {
      const keys = Object.keys(postgresDBModels);
      return Promise.all(keys.map(currentItem => {
        return postgresDB.models[currentItem].schema(client.code).sync();
      }));
    }).
    then(() => console.log('Postgres schema created')).
    catch((err) => {
      console.log(err);
    });
};
createUser();

【讨论】:

    【解决方案3】:

    问题在于 createUser 函数内部的同步 data.forEach() 调用,它没有等待异步 createSchema 调用在返回之前完成。 您可以通过使用 forEach 函数的异步实现或使用 Promise.all() 来解决此问题

    这是一段可能对你有用的代码:

    const createUser = () => {
      return Home.findAll({
        raw: true
      }).then((data) => Promise.all(
        data.map((client) => postgresDB.createSchema(client.code).then(() =>
          Promise.all(Object.keys(postgresDB.models).map((currentItem) =>
            postgresDB.models[currentItem].schema(client.code).sync()
          ))
        ))
      ))
        .catch((err) => {
          console.log('Warning:', err.message);
        });
    };

    【讨论】:

      【解决方案4】:

      为了让 Promise 链起作用,您必须为任何异步函数返回一个 Promise,否则它不会等待。您还将为您迭代的每个客户端进行另一个异步调用。为了一次处理多个 Promise,您需要将每个 Promise 推入一个数组并将其传递给Promise.all。这是一个应该可以工作的 sn-p。

      const createUser = () => {
        return Home.findAll({
          raw: true,
        }).then((data) => {
          const promises = [];
          data.forEach((client) => {
            promises.push(
              postgresDB.createSchema(client.code).then(() => {
                Object.keys(postgresDB.models).forEach((currentItem) => {
                   postgresDB.models[currentItem].schema(client.code).sync();
                   console.log('Postgres schema created');
                })
              })
            );
          });
          return Promise.all(promises);
        }).catch((err) => {
          console.log('Warning:', err.message);
        });
      };
      

      【讨论】:

      • @MohamedSameer Promises 是 JavaScript 的新补充,回调是在 Promise 被添加到语言规范之前处理异步代码的旧方法。我建议尽可能使用 promises 和 async await 而不是回调,因为它可以使代码更简洁;但是,较旧的 API 使用回调,因此您不得不使用它们。
      • 我使用了你的代码,它仍然是异步的,我的下面的代码以前可以工作!
      • @MohamedSameer 我很抱歉。由于意外嵌套,我的代码格式有点错误。试试我编辑的版本。
      • 好的,等我检查一下
      • @MohamedSameer 运气好吗?
      猜你喜欢
      • 1970-01-01
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 2016-02-05
      • 2014-09-27
      • 2019-03-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多