在返回数据之前等待完成异步函数的最佳方法

时间:2017-03-14 10:25:13

标签: javascript arrays asynchronous request promise

在返回数据之前等待完成所有并行异步函数的最佳方法是什么?

请求以异步方式工作,以下函数将返回一个空数组。

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 :(
}

4 个答案:

答案 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))