繁体   English   中英

多次调用异步函数

[英]Calling async function multiple times

所以我有一个方法,我想在循环中多次调用它。 这是函数:

function PageSpeedCall(callback) {
    var pagespeedCall = `https://www.googleapis.com/pagespeedonline/v4/runPagespeed?url=https://${websites[0]}&strategy=mobile&key=${keys.pageSpeed}`;
    // second call
    var results = '';
    https.get(pagespeedCall, resource => {
        resource.setEncoding('utf8');
        resource.on('data', data => {
            results += data;
        });
        resource.on('end', () => {
            callback(null, results);
        });
        resource.on('error', err => {
            callback(err);
        });
    });
    // callback(null, );
}

如您所见,这是一个调用 PageSpeed API 的异步函数。 然后它通过callback获得响应并将其呈现在视图中。 现在我如何让它在 for/while 循环中工作? 例如

function PageSpeedCall(websites, i, callback) {
    var pagespeedCall = `https://www.googleapis.com/pagespeedonline/v4/runPagespeed?url=https://${websites[i]}&strategy=mobile&key=${keys.pageSpeed}`;
    // second call
    var results = '';
    https.get(pagespeedCall, resource => {
        resource.setEncoding('utf8');
        resource.on('data', data => {
            results += data;
        });
        resource.on('end', () => {
            callback(null, results);
        });
        resource.on('error', err => {
            callback(err);
        });
    });
    // callback(null, );
}

var websites = ['google.com','facebook.com','stackoverflow.com'];
for (let i = 0; i < websites.length; i++) {
    PageSpeedCall(websites, i);
}

我想为这些网站中的每一个获得一份报告。 数组的长度将根据用户的操作而变化。

我正在使用async.parallel来调用这样的函数:

let freeReportCalls = [PageSpeedCall, MozCall, AlexaCall];

async.parallel(freeReportCalls, (err, results) => {
    if (err) {
        console.log(err);
    } else {
        res.render('reports/report', {
            title: 'Report',
            // bw: JSON.parse(results[0]),
            ps: JSON.parse(results[0]),
            moz: JSON.parse(results[1]),
            // pst: results[0],
            // mozt: results[1],
            // bw: results[1],
            al: JSON.parse(results[2]),
            user: req.user,
        });
    }
});

我尝试使用承诺链,但由于某种原因,我无法将它放在我的脑海中。 这是我的尝试。

return Promise.all([PageSpeedCall,MozCall,AlexaCall]).then(([ps,mz,al]) => {
    if (awaiting != null)
        var areAwaiting = true;
    res.render('admin/', {
        title: 'Report',
        // bw: JSON.parse(results[0]),
        ps: JSON.parse(results[0]),
        moz: JSON.parse(results[1]),
        // pst: results[0],
        // mozt: results[1],
        // bw: results[1],
        al: JSON.parse(results[2]),
        user: req.user,
    });
}).catch(e => {
    console.error(e)
});

我尝试这样做:

return Promise.all([for(let i = 0;i < websites.length;i++){PageSpeedCall(websites, i)}, MozCall, AlexaCall]).
then(([ps, mz, al]) => {
    if (awaiting != null)
        var areAwaiting = true;
    res.render('admin/', {
        title: 'Report',
        // bw: JSON.parse(results[0]),
        ps: JSON.parse(results[0]),
        moz: JSON.parse(results[1]),
        // pst: results[0],
        // mozt: results[1],
        // bw: results[1],
        al: JSON.parse(results[2]),
        user: req.user,
    });
}).catch(e => {
    console.error(e)
});

但是节点只是说它很愚蠢。

如果我不想将网站和迭代器传递给函数,这将起作用。 知道如何解决这个问题吗?

回顾一下。 到目前为止,这些功能适用于单个网站。 我希望他们为一系列网站工作。

我基本上不知道如何调用它们,以及如何返回响应。

如果你使用fetchasync/await容易多了

const fetch = require('node-fetch');

async function PageSpeedCall(website) {
    const pagespeedCall = `https://www.googleapis.com/pagespeedonline/v4/runPagespeed?url=https://${website}&strategy=mobile&key=${keys.pageSpeed}`;
    const result = await fetch(pagespeeddCall);
    return await result.json();
}


async function callAllSites (websites) {
  const results = [];
  for (const website of websites) {
    results.push(await PageSpeedCall(website));
  }
  return results;
}

callAllSites(['google.com','facebook.com','stackoverflow.com'])
  .then(results => console.log(results))
  .error(error => console.error(error));

Promise.all 哪个更好

async function callAllSites (websites) {
  return await Promise.all(websites.map(website => PageSpeedCall(website));
}

从 Node 7.5.0 开始,您可以使用本机 async/await:

async function PageSpeedCall(website) {
  var pagespeedCall = `https://www.googleapis.com/pagespeedonline/v4/runPagespeed?url=https://${website}&strategy=mobile&key=${keys.pageSpeed}`;
  return await promisify(pagespeedCall);
}

async function getResults(){
  const websites = ['google.com','facebook.com','stackoverflow.com'];

  return websites.map(website => {
    try {
      return await PageSpeedCall(website);
    }
    catch (ex) {
      // handle exception
    }
  })
}

节点http“回调”到promise函数:

function promisify(url) {
  // return new pending promise
  return new Promise((resolve, reject) => {
    // select http or https module, depending on reqested url
    const lib = url.startsWith('https') ? require('https') : require('http');
    const request = lib.get(url, (response) => {
      // handle http errors
      if (response.statusCode < 200 || response.statusCode > 299) {
          reject(new Error('Failed to load page, status code: ' + response.statusCode));
        }
      // temporary data holder
      const body = [];
      // on every content chunk, push it to the data array
      response.on('data', (chunk) => body.push(chunk));
      // we are done, resolve promise with those joined chunks
      response.on('end', () => resolve(body.join('')));
    });
    // handle connection errors of the request
    request.on('error', (err) => reject(err))
  })
}

使PageSpeedCall成为一个承诺,并根据需要多次将该承诺推送到数组,例如myArray.push(PageSpeedCall(foo))然后myArray.push(PageSpeedCall(foo2))等等。 然后你 Promise.all 数组。

如果后续的异步调用需要先前异步调用的结果,那就是.then的用途。

Promise.all()

 Promise.all([promise1, promise2, promise3]).then(function(values) { console.log(values); });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM