2017-07-19 91 views
0

我有兩個函數開始異步加載資源。我怎樣才能讓他們回到承諾,我可以等待加載完成?如何爲嵌套的異步調用創建承諾

// #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) 
    ); 
    }); 
    } 

我想獲得一個承諾(或兩個),這樣我可以等到雙方完成後,即文件被加載和模板鏈接。我只是不明白我能如何獲得它們以便它們能夠被返回。簡單地將return放在每個函數的第一行之前將不會爲嵌套任務返回正確的一個。我是否必須在這裏改變我的設計才能夠等待最內在的任務?

+1

唉!你爲什麼使用'$ .when'而不是'Promise.all' –

+0

我剛剛學習ES6,謝謝你的建議。 –

+1

確實[此代碼](https://jsfiddle.net/qombct3f/)解決您的問題?我不太確定你要誠實的承諾 –

回答

1

乾脆把return在每個函數的第一行前將不會返回正確的一個嵌套的任務

事實上它會。你確定你把它放在所有四個函數的第一行嗎?

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) 
    ); 
    }); 
} 

關於LoadMaps,你可能一直在想在同時運行兩個getFile通話方面。你可以做到這一點再次使用Promise.all

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

甚至

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

OP可以通過取消第二次返回來避免第二次返回。 – danh

+0

@danh他可以避免嵌套,但不是回報 – Bergi

+0

啊,好吧,我只想到外面的'return's。如果內部函數也返回promise,那麼外部函數會自動等待它們? –

1

如果你需要的是知道什麼時候最後一次通話已經完成,你可以簡單地使用這個骨架:

function firstCall() { 
 
     return new Promise((y,n) => setTimeout(() => y('firstCall'), 500)); 
 
    } 
 

 
    function secondCall() { 
 
     return new Promise((y,n) => setTimeout(() => y('secondCall'), 800)); 
 
    } 
 

 
    function promiseTest() { 
 
     Promise.all([ 
 
      firstCall(), 
 
      secondCall() 
 
     ]).then(function(data) { 
 
      console.log(data); 
 
     }) 
 
     .catch(function(err) { 
 
      console.log('Error executing promisses.', err); 
 
     }); 
 
    } 
 
    promiseTest();