如何为嵌套异步调用创建Promise [英] How to create a Promise for nested async calls

查看:102
本文介绍了如何为嵌套异步调用创建Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个功能开始异步加载资源。如何让他们退回承诺,我可以等到加载完成?

  //#1 
LoadMaps(){
gFileService.getFile('syn-maps.json')然后(
mapItem => this.synMaps = mapItem
).then(
gFileService。 getFile('sense-maps.json')然后(
mapItem => this.senseMaps = mapItem

);
}

//#2
LoadListAndMetadata(){
gListService.getList()。then(lexList => {
let promises = [ ];
lexList.forEach(lexItem => {
lexItem.selected = false;
this.lexList [lexItem.lexId] = lexItem;
if(lexItem.hasMeta) {
promises.push(gFileService.getFile(lexItem.metaFile).then(
metaItem => this.metadata [lexItem.lexId] = metaItem
));
}
});
$ .when(... promises).then(
()=> $ .templates('#lexSelectionTemplate')。link('#lexSelection' )
);
});
}

我想获得一个承诺(或两个),以便我可以等待直到两者都完成,即文件被加载并且模板被链接。我只是看不到如何获得他们,以便他们可以退回。在每个函数的第一行之前简单地将返回将不会返回正确的嵌套任务。我必须改变我的设计才能等到最内层的任务吗?

解决方案


在每个函数的第一行之前简单地将 return 返回正确的嵌套任务


其实它会的。你确定你把它放在所有四个函数的第一行吗?

  LoadMaps(){
return gFileService。 getFile('syn-maps.json')然后(
// ^^^^^^
mapItem => this.synMaps = mapItem
).then(()=> ; {//< ==诚然,你忘了这个整个函数
返回gFileService.getFile('sense-maps.json')然后(
// ^^^^^^
mapItem => this.senseMaps = mapItem

});
}

LoadListAndMetadata(){
return gListService.getList()然后(lexList => {
// ^^^^^^
let promises = [];
lexList.forEach(lexItem => {
lexItem.selected = false;
this.lexList [lexItem.lexId] = lexItem;
if (lexItem.hasMeta){
promises.push(gFileService.getFile(lexItem.metaFile).then(
metaItem => this.metadata [lexItem.lexId] = metaItem
));
}
});
返回Promise.all(promises).then(
// ^^^^^^
()=> $ .templates ('#lexSelectionTemplate')。link('#lexSelection',this)
);
});
}






关于 LoadMaps ,您可能一直在考虑同时运行两个 getFile 调用。您可以使用 Promise.all 再次执行此操作:

  LoadMaps() {
return Promise.all([
// ^^^^^^
gFileService.getFile('syn-maps.json')。then(mapItem =>
this.synMaps = mapItem
),
gFileService.getFile('sense-maps.json')然后(mapItem =>
this.senseMaps = mapItem

]);
}

甚至

  LoadMaps(){
return Promise.all([
gFileService.getFile('syn-maps.json'),
gFileService.getFile(' sense-maps.json')
])然后(results => {
[this.synMaps,this.senseMaps] = results
});
}


I have two functions which are starting asynchronous loading of resources. How can I make them return promises to that I can wait until the loading is finished?

  // #1
  LoadMaps() {
    gFileService.getFile('syn-maps.json').then(
      mapItem => this.synMaps = mapItem
    ).then(
      gFileService.getFile('sense-maps.json').then(
        mapItem => this.senseMaps = mapItem
      )
    );
  }

  // #2
  LoadListAndMetadata() {
    gListService.getList().then(lexList => {
      let promises = [];
      lexList.forEach(lexItem => {
        lexItem.selected = false;
        this.lexList[lexItem.lexId] = lexItem;
        if (lexItem.hasMeta) {
          promises.push(gFileService.getFile(lexItem.metaFile).then(
            metaItem => this.metadata[lexItem.lexId] = metaItem
          ));
        }
      });
      $.when(...promises).then(
        () => $.templates('#lexSelectionTemplate').link('#lexSelection', this)
      );
    });
  }

I would like to get a Promise (or two) so that I can wait until both are finished, i.e. the files are loaded and the template is linked. I just don't see how I could obtain them so that they can be returned. Simply putting return in front of the first line of each function will not return the correct one for the nested tasks. Do I have to change my design here to be able to wait on the innermost tasks?

解决方案

Simply putting return in front of the first line of each function will not return the correct one for the nested tasks

Actually it will. Are you sure your put it on the first line of all four functions?

LoadMaps() {
  return gFileService.getFile('syn-maps.json').then(
//^^^^^^
    mapItem => this.synMaps = mapItem
  ).then(() => { // <== admittedly, you forgot this entire function
    return gFileService.getFile('sense-maps.json').then(
//  ^^^^^^
      mapItem => this.senseMaps = mapItem
    )
  });
}

LoadListAndMetadata() {
  return gListService.getList().then(lexList => {
//^^^^^^
    let promises = [];
    lexList.forEach(lexItem => {
      lexItem.selected = false;
      this.lexList[lexItem.lexId] = lexItem;
      if (lexItem.hasMeta) {
        promises.push(gFileService.getFile(lexItem.metaFile).then(
          metaItem => this.metadata[lexItem.lexId] = metaItem
        ));
      }
    });
    return Promise.all(promises).then(
//  ^^^^^^
      () => $.templates('#lexSelectionTemplate').link('#lexSelection', this)
    );
  });
}


Regarding LoadMaps, you might have been thinking in terms of running the two getFile calls concurrently. You can do that using Promise.all again:

LoadMaps() {
  return Promise.all([
//^^^^^^
    gFileService.getFile('syn-maps.json').then(mapItem =>
      this.synMaps = mapItem
    ),
    gFileService.getFile('sense-maps.json').then(mapItem =>
      this.senseMaps = mapItem
    )
  ]);
}

or even

LoadMaps() {
  return Promise.all([
    gFileService.getFile('syn-maps.json'),
    gFileService.getFile('sense-maps.json')
  ]).then(results => {
    [this.synMaps, this.senseMaps] = results
  });
}

这篇关于如何为嵌套异步调用创建Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆