Node.js中的同步请求

How*_*ard 95 synchronization node.js

如果我需要按顺序调用3个http API,那么对于以下代码来说,这将是一个更好的替代方法:

http.get({ host: 'www.example.com', path: '/api_1.php' }, function(res) { 
  res.on('data', function(d) { 

    http.get({ host: 'www.example.com', path: '/api_2.php' }, function(res) { 
      res.on('data', function(d) { 

        http.get({ host: 'www.example.com', path: '/api_3.php' }, function(res) { 
          res.on('data', function(d) { 


          });
        });
        }
      });
    });
    }
  });
});
}
Run Code Online (Sandbox Code Playgroud)

Ray*_*nos 68

使用延迟类似Futures.

var sequence = Futures.sequence();

sequence
  .then(function(next) {
     http.get({}, next);
  })
  .then(function(next, res) {
     res.on("data", next);
  })
  .then(function(next, d) {
     http.get({}, next);
  })
  .then(function(next, res) {
    ...
  })
Run Code Online (Sandbox Code Playgroud)

如果你需要通过范围,那么就做这样的事情

  .then(function(next, d) {
    http.get({}, function(res) {
      next(res, d);
    });
  })
  .then(function(next, res, d) { })
    ...
  })
Run Code Online (Sandbox Code Playgroud)

  • 即使根据"期货"的作者,ES6 Promise API也应该有效地取代它 (4认同)

Jos*_*osh 53

我也喜欢Raynos的解决方案,但我更喜欢不同的流控制库.

https://github.com/caolan/async

根据您是否需要每个后续函数的结果,我要么使用系列,并行或瀑布.

系列必须连续执行时,但在每个后续函数调用中不一定需要结果.

并行如果它们可以并行执行,则在每个并行函数期间不需要每个结果,并且在完成所有并行操作时需要回调.

瀑布如果你想在每个函数中变形结果并传递给下一个函数

endpoints = 
 [{ host: 'www.example.com', path: '/api_1.php' },
  { host: 'www.example.com', path: '/api_2.php' },
  { host: 'www.example.com', path: '/api_3.php' }];

async.mapSeries(endpoints, http.get, function(results){
    // Array of results
});
Run Code Online (Sandbox Code Playgroud)

  • var http = require('http'); (9认同)
  • 哈.example.com实际上是为这类事物设计的域名.哇. (7认同)

小智 33

您可以使用我的公共节点库执行此操作:

function get(url) {
  return new (require('httpclient').HttpClient)({
    method: 'GET',
      url: url
    }).finish().body.read().decodeToString();
}

var a = get('www.example.com/api_1.php'), 
    b = get('www.example.com/api_2.php'),
    c = get('www.example.com/api_3.php');
Run Code Online (Sandbox Code Playgroud)

  • 废话,我upvoted认为它会工作,它不会:(`require(...).HttpClient不是一个构造函数 (2认同)

jem*_*oii 28

同步请求

到目前为止,我发现和使用的最简单的是sync-request,它支持节点和浏览器!

var request = require('sync-request');
var res = request('GET', 'http://google.com');
console.log(res.body.toString('utf-8'));
Run Code Online (Sandbox Code Playgroud)

就是这样,没有疯狂的配置,没有复杂的lib安装,尽管它确实有一个lib回退.只是工作.我在这里尝试了其他的例子,当有很多额外的设置要做或安装不起作用时难倒!

笔记:

同步请求使用的示例在您使用时不会很好res.getBody(),所有get body都接受编码并转换响应数据.只是做res.body.toString(encoding).


gen*_*nry 20

我将使用带有apis列表的递归函数

var APIs = [ '/api_1.php', '/api_2.php', '/api_3.php' ];
var host = 'www.example.com';

function callAPIs ( host, APIs ) {
  var API = APIs.shift();
  http.get({ host: host, path: API }, function(res) { 
    var body = '';
    res.on('data', function (d) {
      body += d; 
    });
    res.on('end', function () {
      if( APIs.length ) {
        callAPIs ( host, APIs );
      }
    });
  });
}

callAPIs( host, APIs );
Run Code Online (Sandbox Code Playgroud)

编辑:请求版本

var request = require('request');
var APIs = [ '/api_1.php', '/api_2.php', '/api_3.php' ];
var host = 'www.example.com';
var APIs = APIs.map(function (api) {
  return 'http://' + host + api;
});

function callAPIs ( host, APIs ) {
  var API = APIs.shift();
  request(API, function(err, res, body) { 
    if( APIs.length ) {
      callAPIs ( host, APIs );
    }
  });
}

callAPIs( host, APIs );
Run Code Online (Sandbox Code Playgroud)

编辑:请求/异步版本

var request = require('request');
var async = require('async');
var APIs = [ '/api_1.php', '/api_2.php', '/api_3.php' ];
var host = 'www.example.com';
var APIs = APIs.map(function (api) {
  return 'http://' + host + api;
});

async.eachSeries(function (API, cb) {
  request(API, function (err, res, body) {
    cb(err);
  });
}, function (err) {
  //called when all done, or error occurs
});
Run Code Online (Sandbox Code Playgroud)


Ale*_*hin 5

似乎这个问题的解决方案永无止境,这里还有一个:)

// do it once.
sync(fs, 'readFile')

// now use it anywhere in both sync or async ways.
var data = fs.readFile(__filename, 'utf8')
Run Code Online (Sandbox Code Playgroud)

http://alexeypetrushin.github.com/synchronize


Nat*_*ate 5

另一种可能性是建立一个跟踪已完成任务的回调:

function onApiResults(requestId, response, results) {
    requestsCompleted |= requestId;

    switch(requestId) {
        case REQUEST_API1:
            ...
            [Call API2]
            break;
        case REQUEST_API2:
            ...
            [Call API3]
            break;
        case REQUEST_API3:
            ...
            break;
    }

    if(requestId == requestsNeeded)
        response.end();
}
Run Code Online (Sandbox Code Playgroud)

然后只需为每个ID分配一个ID,您就可以在关闭连接之前设置必须完成哪些任务的要求.

const var REQUEST_API1 = 0x01;
const var REQUEST_API2 = 0x02;
const var REQUEST_API3 = 0x03;
const var requestsNeeded = REQUEST_API1 | REQUEST_API2 | REQUEST_API3;
Run Code Online (Sandbox Code Playgroud)

好吧,它不漂亮.这只是进行顺序调用的另一种方式.不幸的是NodeJS没有提供最基本的同步调用.但我理解异步性的诱惑是什么.


vde*_*nne 5

截至 2018 年,使用 ES6 模块和 Promises,我们可以编写这样的函数:

import { get } from 'http';

export const fetch = (url) => new Promise((resolve, reject) => {
  get(url, (res) => {
    let data = '';
    res.on('end', () => resolve(data));
    res.on('data', (buf) => data += buf.toString());
  })
    .on('error', e => reject(e));
});
Run Code Online (Sandbox Code Playgroud)

然后在另一个模块中

let data;
data = await fetch('http://www.example.com/api_1.php');
// do something with data...
data = await fetch('http://www.example.com/api_2.php');
// do something with data
data = await fetch('http://www.example.com/api_3.php');
// do something with data
Run Code Online (Sandbox Code Playgroud)

代码需要在异步上下文中执行(使用async关键字)