2016-07-29 46 views
3

我有一個在NodeJS Express中定義的路由。節點js - 在所有承諾解決後發送響應

路由多次調用一個函數(返回一個promise)。從這些Promise返回的值被添加到數組中,然後使用res.json()將數組發送回客戶端。

我面臨的問題是,雖然Promise得到解決,但res.json()會執行,因爲它不會等待Promise返回。我認爲需要某種鏈接機制,但是不知道如何去做。

下面是我的代碼

app.get('/markers', function(req, res) { 
     var markers = []; 
    var marker1 = {"id": 1, "name": "London"}; 
// Get the lat and lng based on the address 
    geocoding(marker1.name).then(function(geocode) { 
     marker1.lat = geocode[0].latitude; 
     marker1.lng = geocode[0].longitude; 
     markers.push(marker1); 
    }, function(error) { 
     console.log(error); 
    }) 

    var marker2 = {"id": 2, "name": "Chicago" }; 
    geocoding(marker2.name).then(function(geocode) { 
     marker2.lat = geocode[0].latitude; 
     marker2.lng = geocode[0].longitude; 
     markers.push(marker2); 
    }, function(error) { 
     console.log(error); 
    }) 
    var marker3 = {"id": 3, "name": "Munich" }; 
    geocoding(marker3.name).then(function(geocode) { 
     marker3.lat = geocode[0].latitude; 
     marker3.lng = geocode[0].longitude; 
     markers.push(marker3); 
    }, function(error) { 
     console.log(error); 
    }) 
    // return the lat and lng array to the client 
    res.json(markers); 

}) 

我怎樣才能確保 'res.json(標記);'在所有三個Promise解決後執行。

回答

5

你只需要使用Promise.all,當所有的承諾都解決了,這將解決:

app.get('/markers', function(req, res) { 
    var markers = []; 
    var marker1 = {"id": 1, "name": "London"}; 

// Get the lat and lng based on the address 
    var prom1 = geocoding(marker1.name).then(function(geocode) { 
     marker1.lat = geocode[0].latitude; 
     marker1.lng = geocode[0].longitude; 
     markers.push(marker1); 
    }, function(error) { 
     console.log(error); 
    }) 

    var marker2 = {"id": 2, "name": "Chicago" }; 
    var prom2 = geocoding(marker2.name).then(function(geocode) { 
     marker2.lat = geocode[0].latitude; 
     marker2.lng = geocode[0].longitude; 
     markers.push(marker2); 
    }, function(error) { 
     console.log(error); 
    }); 

    var marker3 = {"id": 3, "name": "Munich" }; 
    var prom3 = geocoding(marker3.name).then(function(geocode) { 
     marker3.lat = geocode[0].latitude; 
     marker3.lng = geocode[0].longitude; 
     markers.push(marker3); 
    }, function(error) { 
     console.log(error); 
    }); 
    // return the lat and lng array to the client 

    Promise.all([prom1, prom2, prom3]).then(function() {res.json(markers);}).catch(function(err) {console.error(err);}); 
}) 
0

你可以等待使用Promise.all功能多承諾的結果。您也可以使用Array.prototype.map準備一組承諾以減少代碼重複。

而你應該妥善處理承諾拒絕。

app.get('/markers', function(req, res, next) { 
    var markers = [{ 
    id: 1, 
    name: 'London' 
    }, { 
    id: 2, 
    name: 'Chicago' 
    }, { 
    id: 3, 
    name: 'Munich' 
    }]; 
    // you could use .map to generate an array of promises 
    var promises = markers.map(function (marker) { 
    return geocoding(marker.name); 
    }) 
    // and then use Promise.all to await their results 
    Promise.all(promises).then(function (geocodes) { 
    // you could use .map again to generate resulting json 
     res.json(geocodes.map(function (geocode) { 
     return { 
     lat: geocode[0].latitude, 
     lng: geocode[0].longitude 
     } 
    })); 
    }).catch(next) // handle promise rejection 
})