【问题标题】:ES6 Promises confusionES6 Promises 混乱
【发布时间】:2021-08-06 02:14:52
【问题描述】:

我在异步函数中有以下 sn-p 代码 -

  await application.save((err) => {
    console.log("hello");
    if (err) {
      res.status(500).send({ message: "Error encountered" });
    }
  });
  console.log("hey");

为什么“嘿”比“你好”更早打印出来?以及如何修复它以使行为符合预期(等待异步保存操作,只有当它完成并打印“hello”时,才应该打印“hey”)。

以下代码确实将对象保存到 MongoDB,但是当我使用 application.save().then(() => {}) 时,我收到错误“无法读取未定义的属性 'then'”

【问题讨论】:

标签: javascript node.js express mongoose


【解决方案1】:

你混淆了回调和承诺。

例如,我们有第一个任务 F、长任务 T 和下一个任务 N。我们希望确保代码按 F -> T -> N 的顺序运行。为此,我们需要回调或承诺。

回调

function F() {}

function T(cb) {
  // do that long task here
  cb(err); // then call the cb and pass is the err
}

function N() {}

function main() {
  F();
  cb = (err) => {
    if (err) { // handle err }
    else {
      N() // N needs to be run in cb
    }
    // clean up
    // N can also be put here if you want to guarantee N will run
  };
  T(cb);
}

承诺

function F() {}

function T(cb) {
  return new Promise((resolve, reject) => {
        // do that long task here
        if(err) {
            reject();
        } else {
            resolve();
        }
    });
}

function N() {}

// using .then .catch .final
function main() {
  F();
  T().then(N())
     .catch(() => {
       // handle error
     })
     .finally(() => {
       // clean up
       // N can also be put here if you want to guarantee N will run
     })
}

// using async/await
async function main() {
  F();
  try {
    await T();
    N();
  } catch {
    // handle error
  } finally {
    // clean up
    // N can also be put here if you want to guarantee N will run
  }
}

在您的情况下,save() 函数不返回承诺,但希望传入回调。如果您想要一个快速简单的解决方案,请将您的 console.log("hey"); 放入回调中。更好的方法是 promisify 该回调函数,以便它返回一个 Promise 并且您可以等待它。这是一个示例 Promisify 函数,用于将接受回调的函数转换为返回 Promise 的函数:

来自

function T(...args, cb) {
  // do that long task here
  cb(err, data)
}

function TAsync(...args) {
  return new Promise((resolve, reject) => {
    T(...args, function(err, data) {
      if (err) reject(err)
      else resolve(data)
    });
  });
}

【讨论】:

    【解决方案2】:

    如果一个函数返回一个 promise,你只需要使用 await 并将返回值分配给一个作为响应的变量。您应该始终使用 try catch,因为 Promise 会引发异常。

    function divide(i, j) {
        return new Promise((resolve, reject) => {
            if(j == 0) {
                reject("division by zero.");
            } else {
                resolve(i / j);
            }
        });
    }
    
    async function main() {
        try {
            let resp = await divide(5, 2);
            console.log(`resp = ${resp}`);
            resp = await divide(2, 0);
            console.log(`resp 2 = ${resp}`);
        } catch(e) {
            console.log(`catch = ${e}`);
        }
    }
    // another way to use promises
    divide(5,2).then((resp) => {
        console.log(resp);
    }).catch((err) => {
        console.log(err);
    });
    divide(5,0).then((resp) => {
        console.log(resp);
    }).catch((err) => {
        console.log(err);
    });
    
    main();
    

    可能你的函数没有返回一个承诺。

    【讨论】:

      猜你喜欢
      • 2016-05-10
      • 1970-01-01
      • 2015-11-08
      • 2016-06-15
      • 1970-01-01
      • 2012-02-06
      • 2010-12-04
      • 2011-05-05
      • 2018-05-30
      相关资源
      最近更新 更多