如何将Promise.spread迁移为结合解构的async/await?Sequelize场景遇阻
解决Sequelize findOrCreate用await解构失败的问题
哈哈,这个坑我之前刚踩过!你遇到的问题十有八九是Sequelize版本差异导致的,给你唠唠怎么回事儿以及解决办法:
为啥解构会报错?
在比较老的Sequelize版本(比如v4及以前)里,findOrCreate返回的不是原生的Promise,而是Bluebird库的Promise实例,它resolve的结果也不是一个普通数组——而是一个带有.spread()方法的特殊对象。这时候你直接用数组解构const [user, created] = await ...肯定会出问题,因为它本质上不是数组,只是Bluebird提供了spread方法让你能拆分这两个返回值。
而新版本的Sequelize(v5及以上)已经把这个逻辑改了,findOrCreate的Promise会直接resolve成一个包含[实例对象, 创建状态布尔值]的原生数组,这时候你的解构写法就完全正常了。
两种解决思路
思路1:升级Sequelize(推荐)
如果你的项目依赖允许升级,直接把Sequelize升到v5或更高版本,之后你原来写的:
const [user, created] = await User.findOrCreate({ where: { mcId }, defaults })
就能完美运行,不需要改其他代码。
思路2:在旧版本里手动转成数组
如果暂时没法升级,那我们就把Bluebird返回的特殊对象转成原生数组就行,有两种简单方式:
方式A:用spread包装成数组
const [user, created] = await User.findOrCreate({ where: { mcId }, defaults }) .spread((userObj, isCreated) => [userObj, isCreated]);
方式B:直接用then提取值
const [user, created] = await User.findOrCreate({ where: { mcId }, defaults }) .then(res => [res[0], res[1]]);
两种方式本质都是把特殊对象转换成数组,这样解构语法就能识别了。
快速排查验证
你可以先打印一下await后的结果,确认是不是数组:
const result = await User.findOrCreate({ where: { mcId }, defaults }); console.log("结果类型:", typeof result, "是否为数组:", Array.isArray(result));
如果输出显示不是数组,那肯定是版本问题,用上面的思路2就能解决。
内容的提问来源于stack exchange,提问作者Dave Sag
相关产品推荐
相关产品推荐

