栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用外部API调用和findOneAndUpdate循环结果

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用外部API调用和findOneAndUpdate循环结果

您真正缺少的核心是Mongoose API方法也使用“ Promises”,但是您似乎只是从文档或使用回调的旧示例中复制代码。解决方案是仅转换为使用Promises。

处理承诺

Model.find({},{ _id: 1, tweet: 1}).then(tweets =>   Promise.all(    tweets.map(({ _id, tweet }) =>       api.petition(tweet).then(result =>          TweetModel.findoneAndUpdate({ _id }, { result }, { new: true })         .then( updated => { console.log(updated); return updated })      )    )  )).then( updatedDocs => {  // do something with array of updated documents}).catch(e => console.error(e))

除了从回调进行常规转换外,主要更改是

Promise.all()
用于
Array.map()
根据来自
.find()
而不是
for
循环的结果来解析正在处理的输出。实际上,这是您尝试中遇到的最大问题之一,因为
for
不能实际控制异步函数何时解析。另一个问题是“混合回调”,但这就是我们通常仅使用Promises解决的问题。

在中,

Array.map()
我们
Promise
从API调用返回,链接到
findoneAndUpdate()
实际上正在更新文档的。我们还用于
new:true
实际返回修改后的文档。

Promise.all()
允许“承诺数组”解析并返回结果数组。这些您视为
updatedDocs
。这里的另一个优点是内部方法将以“并行”方式而不是串行方式触发。尽管这需要更多资源,但这通常意味着更快的分辨率。

还要注意,我们使用“的投影”

{ _id: 1, tweet: 1}
仅从结果中返回这两个字段,
Model.find()
因为它们是其余调用中唯一使用的字段。当您不使用其他值时,这样做可以节省返回每个结果的整个文档的时间。

您可以简单地

Promise
从中返回
findoneAndUpdate()
,但我只是添加中,
console.log()
这样您就可以看到输出正在触发。

正常的生产用途应该没有它:

Model.find({},{ _id: 1, tweet: 1}).then(tweets =>   Promise.all(    tweets.map(({ _id, tweet }) =>       api.petition(tweet).then(result =>          TweetModel.findoneAndUpdate({ _id }, { result }, { new: true })      )    )  )).then( updatedDocs => {  // do something with array of updated documents}).catch(e => console.error(e))

另一种“调整”可能是使用“蓝鸟”的实施

Promise.map()
,这两者结合共同
Array.map()
Promise
(S)与控制能力运行并行调用的“并发”执行:

const Promise = require("bluebird");Model.find({},{ _id: 1, tweet: 1}).then(tweets =>   Promise.map(tweets, ({ _id, tweet }) =>     api.petition(tweet).then(result =>         TweetModel.findoneAndUpdate({ _id }, { result }, { new: true })    ),    { concurrency: 5 }  )).then( updatedDocs => {  // do something with array of updated documents}).catch(e => console.error(e))

“并行”的替代方案将按顺序执行。如果太多的结果导致太多的API调用和写回数据库的调用,则可以考虑以下方法:

Model.find({},{ _id: 1, tweet: 1}).then(tweets => {  let updatedDocs = [];  return tweets.reduce((o,{ _id, tweet }) =>     o.then(() => api.petition(tweet))      .then(result => TweetModel.findByIdAndUpdate(_id, { result }, { new: true })      .then(updated => updatedDocs.push(updated))    ,Promise.resolve()  ).then(() => updatedDocs);}).then( updatedDocs => {  // do something with array of updated documents}).catch(e => console.error(e))

在这里,我们可以

Array.reduce()
将“承诺”“链接”在一起,从而使它们能够按顺序解决。请注意,结果数组将保留在范围内,并与最后
.then()
添加到连接链末尾的交换掉,因为您需要这种技术来“收集”来自在该“链”中不同点处解决的Promises的结果。


异步/等待

在从NodeJS
V8.x开始的现代环境中(实际上是LTS的当前版本,并且已经存在了一段时间),您实际上已经支持

async/await
。这使您可以更自然地编写自己的流程

try {  let tweets = await Model.find({},{ _id: 1, tweet: 1});  let updatedDocs = await Promise.all(    tweets.map(({ _id, tweet }) =>       api.petition(tweet).then(result =>TweetModel.findByIdAndUpdate(_id, { result }, { new: true })      )    )  );  // Do something with results} catch(e) {  console.error(e);}

如果存在资源问题,甚至可以按顺序处理:

try {  let cursor = Model.collection.find().project({ _id: 1, tweet: 1 });  while ( await cursor.hasNext() ) {    let { _id, tweet } = await cursor.next();    let result = await api.petition(tweet);    let updated = await TweetModel.findByIdAndUpdate(_id, { result },{ new: true });    // do something with updated document  }} catch(e) {  console.error(e)}

还需要注意的是,

findByIdAndUpdate()
它也可以用作与的匹配,
_id
因此您不需要整个查询文档作为第一个参数。


Boulder

最后一点,如果您实际上根本不需要更新的文档作为响应,那么这

bulkWrite()
是更好的选择,它允许写入操作通常在单个请求中在服务器上进行处理:

Model.find({},{ _id: 1, tweet: 1}).then(tweets =>   Promise.all(    tweets.map(({ _id, tweet }) => api.petition(tweet).then(result => ({ _id, result }))  )).then( results =>  Tweetmodel.bulkWrite(    results.map(({ _id, result }) =>       ({ updateOne: { filter: { _id }, update: { $set: { result } } } })    )  )).catch(e => console.error(e))

或通过

async/await
语法:

try {  let tweets = await Model.find({},{ _id: 1, tweet: 1});  let writeResult = await Tweetmodel.bulkWrite(    (await Promise.all(      tweets.map(({ _id, tweet }) => api.petition(tweet).then(result => ({ _id, result }))    )).map(({ _id, result }) =>      ({ updateOne: { filter: { _id }, update: { $set: { result } } } })    )  );} catch(e) {  console.error(e);}

上面显示的所有组合几乎都可以更改为该组合,因为该

bulkWrite()
方法采用指令的“数组”,因此您可以从上述每个方法中经过处理的API调用构造该数组。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/409721.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号