在返回数据之前等待完成所有并行异步函数的最佳方法是什么?
请求以异步方式工作,以下函数将返回一个空数组。
import request from 'request'
// List of urls
const urls = [
'http://someurl.com/1.json',
'http://someurl.com/2.json',
'http://someurl.com/3.json',
]
function getData () {
// An array that will contain data
let result = []
// Request data from all urls
urls.forEach(i => {
// Function works asynchronously
request(i, (err, res, body) => {
if(err) throw err
const data = JSON.parse(body)
result.push(i.someValue)
})
})
return result // Returns an empty array :(
}
答案 0 :(得分:2)
如果您可以使用承诺,最好的方法是使用它们。 确保您的请求函数返回一个promise,这样您就可以:
var request = function request( url ) {
return new Promise(function requestPromise( resolve, reject ) {
myAjaxCallOrOtherAsyncCall( url, function( error, response ) {
if (error) reject(error);
else resolve(response);
})
});
};
var getData = function getData( urls ) {
return Promise.all( urls.map(request) );
};
var urls = [
'http://someurl.com/1.json',
'http://someurl.com/2.json',
'http://someurl.com/3.json',
];
getData(urls).then(function( responses ) {
var results = responses.map(JSON.parse);
// do somethign with async results
});
答案 1 :(得分:0)
使用Promise.all()
等待所有承诺完成,但这确实需要您使用返回承诺的请求库,例如axios
。
import axios from 'axios'
// List of urls
const urls = [
'http://someurl.com/1.json',
'http://someurl.com/2.json',
'http://someurl.com/3.json',
]
function getData() {
return new Promise((resolve, reject) => {
const promises = urls.map(url => axios.get(url)); // array of pending promises
Promise.all(promises) // creates single promise that resolves when all `promises` resolve
.then(responses => {
const dataArray = responses.map(response => response.data);
return resolve(dataArray);
}) // resolves with an array of response data
.catch(reject);
})
}
getData()
.then(data => {
// do something
})
答案 2 :(得分:0)
尝试使用触发器。收集所有数据后,使用
StreamWriter
然后将其作为处理程序
$(trigger_obj).trigger('loading_complete');
答案 3 :(得分:0)
使用https://github.com/request/request-promise-native,您可以像其他人已经指出的那样促进Promise.all
:
import Request from 'request-promise-native'
// List of urls
const urls = [
'http://someurl.com/1.json',
'http://someurl.com/2.json',
'http://someurl.com/3.json',
]
// The simplest form to create a bunch of request promises:
Promise.all(urls.map(Request))
// Otherwise it could look as follows:
const urlPromises = urls.map(url => Request({
uri: 'http://www.google.com'
// and more options
}))
// Or with promise chains:
const urlPromiseChain = (url) => {
return Request(url)
.then(doSomethingWithResponse)
.catch(logButDontFailOnError)
}
const urlPromiseChains = urls.map(urlPromiseChain)
Promise.all(urlPromises /* or urlPromiseChains */)
.then(responses => console.log(responses))