Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/464.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何改进这种承诺链并获得相同的行为_Javascript_Typescript_Es6 Promise - Fatal编程技术网

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将使其成为