在Promise内部定义异步函数

5

我正在使用.then编写承诺的代码。现在,我决定改用await/async来编写它。我在promise中调用了一个名为add_Lessons的函数,然后在该函数的.then中调用另一个function。这是我使用.then的代码。

function create_section(sections,course_ID,i) {
return new Promise(
    (resolve) => {
        var s_duration = 0;
        var sname = sections[i].name;
        var s_obj = {
            //some object;
        }
        var section_id;
        DB.section.create(s_obj,function (err, data_s) 
        {
            if (err) return next(err);
            section_id = data_s._id;
            var lesson = sections[i].lessons;
            add_lessons(lesson,section_id,i)
            .then(function(arr){
                resolve(arr);
            })
        });
    }
);
};

下面是使用await/async的代码示例。

function create_section(sections,course_ID,i) {
return new Promise(
    async function resolve() {
        var s_duration = 0;
        var sname = sections[i].name;
        var s_obj = {
           //some obj
        }
        var section_id;
        DB.section.create(s_obj,function (err, data_s) 
        {
            if (err) return next(err);
            section_id = data_s._id;
            var lesson = sections[i].lessons;
            var arr = await add_lessons(lesson,section_id,i)
            resolve(arr);
        });
    }
);
};

使用await/async的代码显示出add_lessons是意外标识符的错误。那么告诉我如何在承诺内定义异步函数?

避免使用Promise构造函数反模式! - Bergi
2个回答

8

您将 async 错误地放在了一个函数前面。这个函数应该是 async 的:

DB.section.create(s_obj,function (err, data_s) 

像这样:

DB.section.create(s_obj, async function (err, data_s)

您只能在具有async关键字的函数内部使用await,而不是在其他具有async关键字的函数内部的所有函数中使用。

但是,您应该传递一个以resolve为参数的函数作为new Promise()构造函数,而不是一个名为resolve的函数本身。不要像这样:

return new Promise(
    async function resolve() {

您应该使用类似以下的内容:
return new Promise(function (resolve, reject) {

而且你可能应该运行reject而不是next(error),所以代码应该改为:

if (err) return next(err);

您可以尝试以下操作:

if (err) return reject(err);

如果您想要拒绝从 create_section() 函数返回的承诺。

您正在混合三种异步控制流:回调函数、承诺和async/await。您需要充分理解它们,才能够在没有问题的情况下将它们结合起来。

我建议编写一个包装器,为所有接受回调函数的函数返回承诺,如下所示:

const sectionCreate = (...args) => new Promise((resolve, reject) => {
  DB.section.create(...args, (err, data) => {
    if (err) {
      return reject(err);
    }
    resolve data;
  });
});

你也可以使用Bluebird的promisify来实现这个功能,现在你就能在async/await流程中轻松使用它了:

async function create_section(sections, course_ID, i) {
    var s_duration = 0;
    var sname = sections[i].name;
    var s_obj = {
       //some obj
    }
    var section_id;
    var data = await sectionCreate(s_obj);
    var section_id = data_s._id;
    var lesson = sections[i].lessons;
    var arr = await add_lessons(lesson, section_id, i);
    return arr;
}

假设add_lessons()返回一个承诺,虽然你的代码中暗示了这一点,但可能并非如此。您可以使用await在承诺上等待,因此可以在返回承诺的函数调用前面使用await
请注意,每个async函数都返回一个承诺,因此您不需要显式地这样做。

谢谢您的帮助...您能否推荐一些学习Node.js的好资料给我...我已经了解了Node.js的基础知识,再次感谢... - akash modi
@akashmodi 我可以推荐 Pedro Teixeira 的 Node Tuts 作为一个不错的开始,网址是 http://nodetuts.com/。我还推荐 CodeSchool: https://www.codeschool.com/courses/real-time-web-with-node-js 和 NodeSchool: https://nodeschool.io/,此外在 YouTube 上也有很多好的教程和讲座。祝你好运! - rsp
@akashmodi 还可以搜索一下 Domenic Denicola 关于 Promises 的演讲。 - rsp

1
const getData = new Promise(async (res, rej) => {
    try {
      const response = await fetch("https://jsonplaceholder.typicode.co2m/todos/1");
      if (!response.ok) {
        return rej("Error while fetch");
      }
      const data = await response.json();
      return res(data);
    } catch (error) {
      return rej(error);
    } 
});

getData
.then(data=>console.log(data))
.catch(err=>console.log(err));

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接