Javascript Promise - 第二个然后在第一个之前运行
Posted
技术标签:
【中文标题】Javascript Promise - 第二个然后在第一个之前运行【英文标题】:Javascript Promise - Second then runs before first one 【发布时间】:2022-01-20 16:16:46 【问题描述】:我创建了一个简单的脚本来获取 Strava 活动并将它们保存到 mongoDB,但我遇到了以下问题:
在获取和提交活动之前,我的数据库连接已断开。以下代码输出:
const stravaApi = require('strava-v3');
const mongoose = require('mongoose');
const Activity = require('./models/Activity');
mongoose.connect(process.env.DB_CONNECTION, () => console.log('connected to DB'))
strava = new stravaApi.client(accessToken)
strava.athlete.listActivities(per_page: 2)
.then(payload =>
let activities = []
for (let strava_activity of payload)
const activity = new Activity(
activityId: strava_activity['id'],
name: strava_activity['name'],
date: strava_activity['start_date'],
type: strava_activity['type'],
distance: strava_activity['distance']
)
activity.save()
.then(data =>
console.log(`Activity from date $strava_activity['start_date'] saved to DB`);
)
.catch(err =>
console.log(err)
)
)
.then(() =>
console.log('Start disconnect')
mongoose.disconnect().then(() =>
console.log("DB disconnected successfully")
)
)
.catch(err =>
console.log(err)
)
输出
connected to DB
DB disconnected successfully
(Error message)
(Error message)
【问题讨论】:
activity.save()
之前的小 return
可能已经成功了。
不,需要更多的重构。
【参考方案1】:
for
循环在其中运行的 then
-callback 不会返回承诺,因此链接到它的 then
-callback 将在下一个微任务中启动。
for
循环中的承诺应该朝着then
-callback 将返回的承诺构建,但activity.save().then(...)
返回的承诺被忽略。
当你使用async
await
语法时,事情变得更容易了:
(async function ()
await mongoose.connect(process.env.DB_CONNECTION);
console.log('connected to DB');
const strava = new stravaApi.client(accessToken);
const payload = await strava.athlete.listActivities(per_page: 2);
for (const id, name, start_date, type, distance of payload)
const activity = new Activity(
activityId: id,
name,
date: start_date,
type,
distance
);
await activity.save();
console.log(`Activity from date $start_date saved to DB`);
console.log('Start disconnect')
await mongoose.disconnect();
console.log("DB disconnected successfully");
)().catch(console.log);
【讨论】:
【参考方案2】:只有在所有 promise 实例都结束时才尝试通过 DB 断开连接,如下所示:
strava.athlete.listActivities(per_page: 2)
.then(payload =>
let activities = []
for (let strava_activity of payload)
const activity = new Activity(
activityId: strava_activity['id'],
name: strava_activity['name'],
date: strava_activity['start_date'],
type: strava_activity['type'],
distance: strava_activity['distance']
)
activity.save()
.then(data =>
console.log(`Activity from date $strava_activity['start_date'] saved to DB`);
)
.catch(err =>
console.log(err)
)
)
.then(() => )
.catch(err =>
console.log(err)
).finally(() =>
console.log('Start disconnect')
mongoose.disconnect().then(() =>
console.log("DB disconnected successfully")
)
)
这样他们只有在咨询结束时才会断开连接
【讨论】:
以上是关于Javascript Promise - 第二个然后在第一个之前运行的主要内容,如果未能解决你的问题,请参考以下文章
在 Promise 中,使用 catch 和 then 的第二个参数有啥区别? [复制]
Javascript 像 Java 8 上的“Promise.all”(可能带有 lambdas)