await 和 循环引用
在项目开发过程中,因为对await和循环引用理解不深刻,导致在运行以下代码时,遇到如下错误:
参考链接:
理解 JavaScript 的 async/await
async 函数的含义和用法(阮一峰)
TypeError: Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at respond (D:\Vue\music\server\node_modules\_koa@2.7.0@koa\lib\application.js:243:15)
at handleResponse (D:\Vue\music\server\node_modules\_koa@2.7.0@koa\lib\application.js:149:34)
at process._tickCallback (internal/process/next_tick.js:68:7)
代码如下:
const Router = require('koa-router')
const router = new Router()
const mongoose = require('mongoose')
router.get('/',async (ctx, next) => {
const swiperImg = mongoose.model('swiperImg')
const songList = mongoose.model('songList')
// find 方法返回一个Promise
const img_list = swiperImg.find({}).sort({
'meta.createdAt': -1
})
const song_list = songList.find({}).sort({
'meta.createdAt': -1
})
ctx.body = {
img_list,
song_list
}
})
module.exports = router
同步:如果在函数A返回的时候,调用者就能够得到预期结果(即拿到了预期的返回值或者看到了预期的效果),那么这个函数就是同步的。
异步:如果在函数A返回的时候,调用者还不能够得到预期结果,而是需要在将来通过一定的手段得到,那么这个函数就是异步的。
********************find()
方法返回的是一个Query
对象(类似于Promise
),我们并不能直接获取到数据,因此,我们该传入一个回调函数,或者异步方法前面添加await
.
const img_list = await swiperImg.find({}).sort({
'meta.createdAt': -1
})
const song_list = await songList.find({}).sort({
'meta.createdAt': -1
})
问题虽然解决了,但是循环引用又是怎么引起的呢?
参考链接
js循环引用的问题
JavaScript变量存储浅析(二)
循环引用的例子
var a={"name":"zzz"};
var b={"name":"vvv"};
a.child=b;
b.parent=a;
回到我们一开始的代码(最开始的代码没有加await对异步方法进行处理),如下
const img_list = swiperImg.find({}).sort({
'meta.createdAt': -1
})
const song_list = songList.find({}).sort({
'meta.createdAt': -1
})
ctx.body = {
img_list,
song_list
}
我们采用console.log(img_list)
查看结果:
Query {
_mongooseOptions: {},
_transforms: [],
_hooks: Kareem { _pres: Map {}, _posts: Map {} },
_executionCount: 0,
mongooseCollection:
NativeCollection {
collection: Collection { s: [Object] },
Promise: [Function: Promise], // 可以看到这里内置了一个Promise对象
opts:
{ bufferCommands: true,
capped: false,
Promise: [Function: Promise],
'$wasForceClosed': undefined },
name: 'swiperimgs',
....
从上面的代码中可以看出Query
对象内置了一个Promise
对象属性,所以可以进行链式操作。
*********
使用console.log(ctx.body)
输出结果为undefined
盲猜Query对象某属性之间存在互相引用。
分析了许久,没有找出那些属性之间发生了循环引用。javascript collection: NativeCollection { collection: [Collection], Promise: [Function: Promise], opts: [Object], name: 'swiperimgs', collectionName: 'swiperimgs', conn: [NativeConnection], queue: [], buffer: false, emitter: [EventEmitter] }, Query: { [Function] base: [Query] }, '$init': Promise { [Circular] }, //在这里发现一个Promise 有个属性值为Circular '$caught': true, [Symbol(mongoose#Model)]: true }
collection:
NativeCollection {
collection: [Collection],
Promise: [Function: Promise],
opts: [Object],
name: 'swiperimgs',
collectionName: 'swiperimgs',
conn: [NativeConnection],
queue: [],
buffer: false,
emitter: [EventEmitter] },
collectionName: 'swiperimgs' },
_traceFunction: undefined,
'$useProjection': true }
难受~~~~~~~
盲猜这里
Query: { [Function] base: [Query] },
'$init': Promise { [Circular] }, //在这里发现一个Promise 有个属性值为Circular
'$caught': true,
-------------------------
collectionName: 'swiperimgs' },
_traceFunction: undefined,
'$useProjection': true }
两段代码之间存在互相引用。