将 Sequelize Promise 嵌入到 javascript async/await 链中

Posted

技术标签:

【中文标题】将 Sequelize Promise 嵌入到 javascript async/await 链中【英文标题】:Embedding a Sequelize promise into a javascript async/await chain 【发布时间】:2019-12-30 23:06:42 【问题描述】:

我正在尝试在现有异步/等待链中使用 Sequelize 承诺。 Sequelize 将所有内容作为承诺返回。我对 promises 和 async/await 不熟悉 所以我把它当作一种学习经验。请对我多一些耐心。

我的逻辑是这样的:

如果前一个'.then'中的行不存在

创建一个新行并提取新的 id

否则

从之前的 '.then' 中提取 id 值

所以现在我有一个 WORKING 代码块(如下),来自研究了许多优秀的 SO 示例。我想使用所有匿名函数,因为恕我直言,它使它更容易阅读。 (是的,有争议的一点,但现在我想尝试使用匿名函数。

三个 嵌套的返回语句似乎很奇怪。有没有办法将这段代码重写为更简洁,但只使用匿名函数?

yourTable.findAll( ...)
.then( (data) => 
      // more code
)
.then( (data) => 
      // more code
)
.then( (data) => 
     if  ( !Array.isArray(data) || !data.length )   
           // if record does NOT exist
         return (async function ()       
             return await
                 (function ()    
                     return new Promise( resolve => 
                         myTable.create(  ........ 
                            ).then( (result) => 
                                resolve(result._id);
                        )
                    )
                )();
            )()    
            /* we had to create one, so we return the *NEW* _id value */
     else 
            /* we found one, so we just return the pre-existing _id value */                                                                                      
        return  data[0]._id    ;
    
)
.then( (data) => 
    // more code
)
.then( (data) => 

谢谢大家。

【问题讨论】:

【参考方案1】:

删除所有不必要的IIFE、IIAFE、return awaitPromise constructor antipattern:

if (!Array.isArray(data) || !data.length) 
    // if record does NOT exist
    const result = await myTable.create( ........ );
    return result._id; // we had to create one, so we return the *NEW* _id value 
 else 
    return data[0]._id; // we found one, so we just return the pre-existing _id value

【讨论】:

这是我尝试的第一件事,我得到了回复:“SyntaxError: await is only valid in async function” 当然,您当然需要对您的then 函数使用async (data) => 回调。但实际上你不应该混合使用 thenawait 语法,而是让外部函数也使用 async/await - 你能告诉我们更多代码吗? 或者如果你不想使用await,它应该是if块中的一个简单的return myTable.create(…).then(result => result._id); "宁可做外部函数" - 好的,我注意了...!我添加了更多代码,但实际上并没有太多其他内容。 您可能应该从const data = await yourTable.findAll( ...); // more code 等开始。然后对于if/else,当您不能只使用return 时,分配给变量(或使用条件运算符)。将所有这些放在 async 函数中(或者,如果它已经在函数中,请添加 async 关键字)。【参考方案2】:

Promise 只是可以是 awaited 的值,但您实际上并不严格需要await 它们,特别是如果您的周围结构没有使用 async/@987654324 @。你可以这样写:

yourTable.findAll( /* ... */ )
    .then((data) => 
        if (!Array.isArray(data) || !data.length) 
            // We need to create one, return the new ID
            return myTable.create( /* ... */ )
                .then((result) => result._id)
         else 
            // We found one, return the existing ID
            return data[0]._id
        
    )

如果您从 .then() 中返回 Promise,它将成为父链的一部分,这可能正是您想要的。

如果您真的想使用async/await,那么我建议您翻转逻辑并在您的快乐路径被计算后做更大的工作:

yourTable.findAll( /* ... */ )
    .then(async (data) => 
        if (data && data.length) return data[0]._id

        const result = await myTable.create( /* ... */ )

        return result._id
    )

【讨论】:

你昨天去哪儿了?你会为我节省几个小时无用的研究。但说真的,非常感谢。我遵循的逻辑有点奇怪,因为我必须阅读其中一个表格两次,但是您的第一个建议效果很好,并使代码更具可读性。我很惊讶这样的情况不会更频繁地发生。您应该在某个地方发布您的出色建议,而不仅仅是在这里。

以上是关于将 Sequelize Promise 嵌入到 javascript async/await 链中的主要内容,如果未能解决你的问题,请参考以下文章

在 Sequelize Hooks 中使用 Promise

有没有办法使用 Sequelize 一次将多个嵌入式模型保存在数据库中

Node.js,ORM框架,Sequelize,入门及增、删、改、查代码案例

Sequelize与async联合使用关于warning:a promise was created but was not returned from it的思考

在 Express.js 中停止执行 Sequelize 承诺

Sequelize 不返回 queryAsync 对象