链接/嵌套承诺



我在尝试链接 aws js sdk 时遇到了噩梦。目前我有以下内容(省略了任何参数来删除谷壳,调用是隔离工作的,因此可以安全地假设它们是正确的)

function deploy() {
return sts.assumeRole().promise()
.then(() => {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
AWS.config.update({
credentials: {
accessKeyId: data.Credentials.AccessKeyId,
secretAccessKey: data.Credentials.SecretAccessKey,
sessionToken: data.Credentials.SessionToken
}
});
resolve();
})
.then(() => {
fsPromise.readFile(packageLocation).then(() => {
return s3.upload().promise();
});
});
}).then(() => {
return ebs.createApplicationVersion().promise();
}).then(() => {
return ebs.createEnvironment().promise();
});
};

如果我按顺序逐个运行每个then它的工作,但是当我一起运行它们时,createApplicationVersion调用失败,因为upload由于它试图在assumeRole完成之前上传而不起作用。我假设...

我显然做错了什么,但我不清楚是什么。

那里使用承诺比必要的要复杂得多。请记住,then(以及catchfinally)返回的新承诺,这些承诺是根据其处理程序返回的内容解决的。then(或catchfinally)处理程序中的new Promise几乎从来都不是必需的;只需返回任何您将用(一个值或另一个承诺)解决该承诺的内容,以及thenET 返回的承诺。将解决它。

如果我假设该链是同步的,则该链应如下所示AWS.config.update()

function deploy() {
return sts.assumeRole().promise()
.then(() => {
AWS.config.update();
})
.then(() => fsPromise.readFile(packageLocation))
.then(() => s3.upload().promise())
.then(() => ebs.createApplicationVersion().promise())
.then(() => ebs.createEnvironment().promise());
}

该链中的每个步骤都将等待上一步完成。

如果您不希望deployebs.createEnvironment().promise()的实现值履行其承诺,请添加最终then处理程序:

.then(() => ebs.createEnvironment().promise())
.then(() => { });
}

(对于以下示例,我假设您要执行此操作。

或者像这样,如果AWS.config.update()是异步的并返回一个承诺:

function deploy() {
return sts.assumeRole().promise()
.then(() => AWS.config.update())
.then(() => fsPromise.readFile(packageLocation))
.then(() => s3.upload().promise())
.then(() => ebs.createApplicationVersion().promise())
.then(() => ebs.createEnvironment().promise())
.then(() => { });
}

或者,当然,在任何相对较新的 Node.js 版本中(我从fsPromise和一般上下文中猜测这是 Node.js),您可以使用async函数:

async function deploy() {
await sts.assumeRole().promise();
await AWS.config.update(); // Or without `await` if it is synchronous and doesn't return a promise
await fsPromise.readFile(packageLocation);
await s3.upload().promise();
await ebs.createApplicationVersion().promise();
await ebs.createEnvironment().promise();
}

关于此代码的旁注,以及您在评论中发布的类似代码:

return new Promise((resolve, reject) => {
AWS.config.update({
credentials: {
accessKeyId: data.Credentials.AccessKeyId,
secretAccessKey: data.Credentials.SecretAccessKey,
sessionToken: data.Credentials.SessionToken
}
});
resolve();
})

没有理由在那里使用new Promise。它不会将AWS.config.update调用转换为异步调用或类似内容。如果出于某种原因你需要一个承诺(在这种情况下你不需要,AKAICT),你会使用Promise.resolve

AWS.config.update(/*...*/);
return Promise.resolve();

但同样,这里不需要。请记住,承诺仅提供一种观察异步过程结果的方法,它们不会使过程异步。(他们实际异步的唯一事情是观察结果。

你不需要像以前那样嵌套你的承诺。在黑暗中刺一刀,试试这个:

function deploy() {
return sts.assumeRole().promise()
.then(() => { AWS.config.update() })
.then(() => fsPromise.readFile(packageLocation))
.then(() => s3.upload().promise())
.then(() => ebs.createApplicationVersion().promise())
.then(() => ebs.createEnvironment().promise())
};

最新更新