Chaining/Nesting 承诺
Chaining/Nesting promises
我在尝试链接 aws js sdk 时遇到了噩梦。目前我有以下内容(省略了任何参数以删除 chaff,调用独立工作,因此可以安全地假设它们是正确的)
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
完成之前上传。我假设...
我显然做错了什么,但我不清楚是什么。
您不需要像以前那样嵌套您的承诺。在黑暗中试一试,试试这个:
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
(以及 catch
和 finally
)return 新承诺 是根据其处理程序 return. then
(或catch
或finally
)处理程序中的new Promise
几乎从不需要;只是 return 无论你用什么来解决这个承诺(一个值或另一个承诺),以及 return 由 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());
}
该链中的每一步都将等待上一步完成。
如果您不希望 deploy
以 ebs.createEnvironment().promise()
的履行值履行其承诺,则添加最终的 then
处理程序:
.then(() => ebs.createEnvironment().promise())
.then(() => { });
}
(对于以下示例,我假设您想这样做。)
或者像这样,如果 AWS.config.update()
是异步的并且 return 是一个承诺:
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();
但同样,这里不需要。请记住,promises 只提供一种方法来观察异步过程的结果,它们不会使过程异步。 (他们实际上使异步的唯一事情是观察结果。)
我在尝试链接 aws js sdk 时遇到了噩梦。目前我有以下内容(省略了任何参数以删除 chaff,调用独立工作,因此可以安全地假设它们是正确的)
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
完成之前上传。我假设...
我显然做错了什么,但我不清楚是什么。
您不需要像以前那样嵌套您的承诺。在黑暗中试一试,试试这个:
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
(以及 catch
和 finally
)return 新承诺 是根据其处理程序 return. then
(或catch
或finally
)处理程序中的new Promise
几乎从不需要;只是 return 无论你用什么来解决这个承诺(一个值或另一个承诺),以及 return 由 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());
}
该链中的每一步都将等待上一步完成。
如果您不希望 deploy
以 ebs.createEnvironment().promise()
的履行值履行其承诺,则添加最终的 then
处理程序:
.then(() => ebs.createEnvironment().promise())
.then(() => { });
}
(对于以下示例,我假设您想这样做。)
或者像这样,如果 AWS.config.update()
是异步的并且 return 是一个承诺:
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();
但同样,这里不需要。请记住,promises 只提供一种方法来观察异步过程的结果,它们不会使过程异步。 (他们实际上使异步的唯一事情是观察结果。)