Javascript 如何改进这种承诺链并获得相同的行为
我需要确保Javascript 如何改进这种承诺链并获得相同的行为,javascript,typescript,es6-promise,Javascript,Typescript,Es6 Promise,我需要确保prepare函数在继续执行之前获得所有值,这就是我链接承诺的原因 这段代码可以工作,但我需要为许多不同的值这样做,代码将是一团混乱,因为链接实际上有嵌套(在then中调用getValue,然后使用then调用getValue等等) 那么,我如何通过更好的实践或更干净的方法实现同样的结果呢 import { BackendService } from "../../core/backend.service"; export class Configuration { assets
prepare
函数在继续执行之前获得所有值,这就是我链接承诺的原因
这段代码可以工作,但我需要为许多不同的值这样做,代码将是一团混乱,因为链接实际上有嵌套(在then中调用getValue
,然后使用then
调用getValue
等等)
那么,我如何通过更好的实践或更干净的方法实现同样的结果呢
import { BackendService } from "../../core/backend.service";
export class Configuration {
assetsBucketAccessKeyId: string ;
assetsBucketSecretAccessKey: string ;
}
export namespace ConfigurationService {
const configurations: { [key: string]: string } = {};
const configurationURL = "configuration";
export const values = new Configuration() ;
export function prepare(backendService: BackendService) {
ConfigurationService
.getValue("assetsBucketAccessKeyId", backendService)
.then(v1 => {values.assetsBucketAccessKeyId = v1; } )
.then(() => { ConfigurationService
.getValue("assetsBucketSecretAccessKey", backendService)
.then(v2 => {values.assetsBucketSecretAccessKey = v2; } ); }) ;
}
export function getValue(
keyName: string,
backendService: BackendService
): Promise<string> {
let resp: string;
resp = null;
return new Promise((resolve, reject) => {
// find or query te value
if (!configurations[keyName]) {
const requestURL = `${configurationURL}/${keyName}`;
backendService.get<string>(requestURL).subscribe(
value => {
configurations[keyName] = value;
resolve(value);
},
error => {
console.log(error);
reject(null);
}
);
} else {
resolve(configurations[keyName]);
}
});
}
}
从“./../core/backend.service”导入{BackendService};
导出类配置{
assetsBucketAccessKeyId:字符串;
assetsBucketSecretAccessKey:字符串;
}
导出命名空间配置服务{
常量配置:{[key:string]:string}={};
const configurationURL=“配置”;
导出常量值=新配置();
导出功能准备(后端服务:后端服务){
配置服务
.getValue(“assetsBucketAccessKeyId”,后端服务)
.然后(v1=>{values.assetsBucketAccessKeyId=v1;})
.然后(()=>{ConfigurationService
.getValue(“assetsBucketSecretAccessKey”,后端服务)
。然后(v2=>{values.assetsBucketSecretAccessKey=v2;});});
}
导出函数getValue(
关键字名称:字符串,
后端服务:后端服务
):承诺{
让我们分别:字符串;
resp=null;
返回新承诺((解决、拒绝)=>{
//查找或查询te值
如果(!配置[keyName]){
const requestURL=`${configurationURL}/${keyName}`;
backendService.get(requestURL.subscribe)(
值=>{
配置[keyName]=值;
决心(价值);
},
错误=>{
console.log(错误);
拒绝(空);
}
);
}否则{
解析(配置[键名]);
}
});
}
}
您可以使用javaScripts async/await sytax来处理承诺,例如
export async function prepare(backendService: BackendService) {
values.assetsBucketAccessKeyId = await ConfigurationService.getValue("assetsBucketAccessKeyId", backendService);
values.assetsBucketSecretAccessKey = await ConfigurationService.getValue("assetsBucketSecretAccessKey", backendService);
}
这种方法在使用承诺时使代码更易于阅读
然后,您可以使用多种方法调用此函数
1) 使用承诺代码来称呼它
prepare(backendService).then(() => { // assetsBucketAccessKeyId/assetsBucketSecretAccessKey will now be available})
2) 从另一个异步方法调用它
async function wrapper() {
await prepare(backendService)
// assetsBucketAccessKeyId/assetsBucketSecretAccessKey now available to access...
}
3) 从匿名函数调用它,例如
(async () => {
await prepare(backendService)
// assetsBucketAccessKeyId/assetsBucketSecretAccessKey now available to access...
})();
由于目标函数已经实现,所以可以使用async await ES6语法 例如:
export async function prepare(backendService: BackendService) {
values.assetsBucketAccessKeyId = await ConfigurationService.getValue(
'assetsBucketAccessKeyId',
backendService
);
values.assetsBucketSecretAccessKey = await ConfigurationService.getValue(
'assetsBucketSecretAccessKey',
backendService
);
}
不要忘记在函数名前面添加async
,在函数调用前面添加wait
注意:
如果您的任何函数没有返回承诺,那么这将不起作用。如果您事先知道所有的键,您可以按顺序运行承诺。串联逻辑非常粗糙,但它基本上是用于此目的的实用方法
下面的更改是所有更改,代码中的所有其他内容都保持不变
您可能需要稍微重构代码,以处理将上下文传递给序列化解析回调的问题,但这很容易
我用的是es7,但是如果你愿意,你可以转换
如果你需要更多的解释,请告诉我
导出异步函数serializedRun(promiseFunctions:(()=>Promise)[],回调:(T)=>void){
//下面的se用于空\/的推理
return wait[…promiseFunctions,null]。reduce(异步(prevPromise、nextPromise、index)=>{
const result=等待承诺;
//跳过初始值承诺
如果(索引==0){
//对每个结果都做些冷静的事情
回调(结果)
}else如果(nextPromise!==null){//跳过最终值
//你需要在最后一个承诺的基础上再进行一次循环,以等待最后一个返回的承诺
返回nextPromise();
}否则{
return Promise.resolve(result);//最终解析值
}
},Promise.resolve());//初始化值承诺开始循环
}
导出命名空间配置服务{
常量配置:{[key:string]:string}={};
const configurationURL=“配置”;
常量键名=[
“assetsBucketAccessKeyId”,
“assetsBucketSecretAccessKey”,
]
导出常量值=新配置();
导出异步函数prepare(后端服务:后端服务){
等待德隆(
//这看起来很疯狂,但你还不想唤起承诺
//因此,您需要返回serializedRun方法可以调用的函数
keyNames.map((键)=>()=>ConfigurationService.getValue(键,后端服务)),
(值)=>{
//您需要找到一种将所需参数传递到此函数的方法
//让它知道该做什么。。。
如果(/*某物*/){
values.assetsBucketAccessKeyId=值;
}否则{
values.assetsBucketSecretAccessKey=值;
}
})
}
注意:您还需要使用try
/catch
块处理serializedRun方法中的任何错误
这使得prepare函数为“async”,那么我该如何等待呢?很抱歉,我看到了你的其他评论。我将在回答中详细说明如何使用此函数。你的结果未定义,可能是因为你的async函数尚未实际运行或完成。请参阅我更新的答案,了解如何调用它并确保结果可用ble.谢谢你的努力,我的问题是我调用prepare的位置不对,如果我能再上一次,我会;-)没问题。很高兴我能帮上忙:)但是“prepare”函数将异步执行,我需要它在下一行被调用之前完全执行。sync wait将与
一样工作。然后()
thing。它将只逐行执行…等待将等待,直到收到数据。仅使用async wait将使代码看起来更好,否则功能将相同,您不需要为v1、v2分配额外变量。在prepare函数前面写入async将使其成为