返回一个promise而不等待nodejs中函数中的依赖promise

Posted

技术标签:

【中文标题】返回一个promise而不等待nodejs中函数中的依赖promise【英文标题】:Return a promise without waiting for a dependant promise in function in nodejs 【发布时间】:2018-05-20 19:30:48 【问题描述】:

我正在使用节点 8.x。因此,我可以使用所有最新功能,例如 async/await 等。

场景类似于以下 (语法不正确,仅供说明):

createUser()

    let userAddress = createAddress(); // Aync, returns a promise
    User.create(name: 'foo', address: userAddress); // User creation is dependant on address. Also, User.create returns a promise.

基本上,用户对象的创建依赖于地址对象的创建。我希望 createUser 函数异步执行,即尽快返回一个承诺,而无需等待创建地址对象。

这个问题的目的不是完成任务,而是了解在异步编程中解决此类问题的最佳方法是什么。

我能想到的几种方法: 1:创建一个新的promise对象并在createUser函数中输入时立即返回。在创建用户对象时解决它。 2:将 createUser 设为异步函数,然后返回 user Promise。此方法面临的问题:

async function createUser()

    address = await createAddress();
    return User.create(name: 'foo', address: userAddress);

问题是函数在返回我不想要的控件之前等待地址。 (或者它不会产生任何差异,因为函数是异步的。在我的情况下,性能是一个重要标准)

当你想要返回父对象的承诺但你的父对象依赖于子对象的承诺时,如何处理这种承诺依赖。

谢谢。

【问题讨论】:

我对你的问题有点困惑......你想在createAddress 完成之前返回User.create(承诺),但User.create 取决于createAddress 是的。我不希望函数等待地址。每当创建地址时,都应该创建用户,因此应该解决承诺。 【参考方案1】:

您可以按原样编写函数,然后取决于它的调用方式。您不能使用await,因为它会在当前范围内阻塞。不过,您可以使用 .then 引入新范围:

async function createUser() 
  address = await createAddress();
  return User.create( name: 'foo', address );

...
createUser().then(() =>  /* handle user creation */ );
// code here will not wait for `createUser` to finish

【讨论】:

【参考方案2】:

将 createUser 设为异步函数,然后返回 user Promise。问题是函数在返回我不想要的控件之前等待地址。

不,它没有。 async function 确实会立即向其调用者返回一个承诺。它仅在执行其主体中的代码时等待(并在您return 时解析承诺)。您的代码有效,这正是您应该做的。

【讨论】:

谢谢。但是,如果我调试或打印到控制台,我发现它肯定不会等待地址被创建(你是对的)但是 - 控件进入 createUser - 然后它也进入 createAddress() 并返回一个承诺 -然后控件返回到调用 createUser 函数的位置。所以异步函数不会立即返回一个承诺。还是我还缺少什么? @AakashMalhotra 啊,是的,直到第一个 await(即 createAddress 调用和承诺创建)之前的所有事情都是同步发生的。只有这样 createUser 才会将其承诺返回给调用者 - 但它仍然是立即,不等待任何承诺兑现。【参考方案3】:

如果createAddress 是一个返回地址的承诺,比如说address,你可以这样做:

createAddress().then(function(address) 
  User.create(name: 'foo', address: address).then(function() 
    // User and address has been created
  )
)

// Do something here that runs even though createAddress has not yet been resolved

这将要求您在执行一些其他代码之前等待承诺得到解决。

【讨论】:

一个then() 在另一个then() 中...这是正确的吗? @robe007 是的 为什么不呢?它基本上只是回调之上的一个相当抽象的概念。 @AakashMalhotra 我说是因为 - 对我来说 - 这被称为 嵌套承诺,我认为有一个 then(): function createUser() return createAddress().then(function(address) return User.create(name: 'foo', address: address) // the return is to handle latter the user creation , function() throw 'Promise Rejected'; ); 就足够了 @feupeu 是的,我知道,但我说的是patterns, best practices, avoid anti-patterns;并且 chaining promises 有他们的owns【参考方案4】:

如果你想返回一个 Promise,那么你基本上是在寻找使用 Promise 的方式:

createUser() 
    return createAddress()
        .then((address) =>
            User.create( name: 'foo', address: address )
        );

现在createUser 方法正在返回一个承诺,该承诺将在未来的某个时候得到解决。您的代码可以继续工作,可以向该承诺添加更多 .then(...).catch(...) 回调,等等。

【讨论】:

createAddress 函数返回的promise 是否在createUser 函数本身中得到解析,createUser() 返回的promise 是User.create 实际返回的promise 吗? 'User.create'函数前不应该有'return'关键字吗? 只要createAddress 解决了这个promise,它就会得到解决——我没有那个函数的细节,所以我不知道它什么时候得到解决。至于您的第二条评论,那就是 ES6“胖箭头”语法 - 请参阅 this link。【参考方案5】:

这是另一种方法,假设 createAddress 返回一个承诺(当然)

function createUser()
    return createAddress().then(function(address) 
        // the return is to handle latter the user creation
        return User.create(name: 'foo', address: address)
    , function() 
        throw 'Promise Rejected';
    );


createUser().then(function(result) 
    console.log("result => " + result);
    // Do something here with the 'user creation' if you want
).catch(function(error) 
    console.log("error => " + error);
);

// Do some stuff, while the code above is executed

【讨论】:

这不正是@Kryten 已经发布的内容吗? (加上多余的throw 这是我的答案!

以上是关于返回一个promise而不等待nodejs中函数中的依赖promise的主要内容,如果未能解决你的问题,请参考以下文章

如何在同步nodejs函数中等待promise?

如何从对象的`get()`获取异步数据而不返回Promise

nodejs之promise书写规范

函数正在返回对象 Promise - nodejs

Promise mysql返回未定义,如何让函数等待结果

NodeJS:等待所有带有 Promises 的 foreach 完成,但从未真正完成