我有以下代码,使用randomuser API
和got
向async.series
发出10个请求。由于某些原因,这只给我一个输出。我该如何解决这个问题?
const got = require('got');
const async = require('async');
var tenOperations = [];
for(var i = 0; i < 10; i++) {
tenOperations.push(doRequest);
}
function doRequest(callback) {
got('https://randomuser.me/api/')
.then(response => {
console.log(response.body);
})
.catch(error => {
console.log(error.response.body);
});
};
async.series(tenOperations, function(err, results) {
if(err) console.log(err);
console.log(results);
});
Here is the sample output
:
{
"results": [
{
"user": {
"gender": "female",
"name": {
"title": "miss",
"first": "غزل",
"last": "كامياران"
},
"location": {
"street": "6186 آزادی",
"city": "رشت",
"state": "تهران",
"zip": 64318
},
"email": "غزل.كامياران@example.com",
"username": "goldenpanda201",
"password": "muscles",
"salt": "OStU2tyA",
"md5": "92ac8a84380a24785597d0e916b0174e",
"sha1": "93f6e830538dbc557017011583cca3b5e527f854",
"sha256": "99a4c35237b1ebe276732fbf62efca24fd457428853de8a967dd465b80b82f0f",
"registered": 1352433856,
"dob": 1370066399,
"phone": "053-14062122",
"cell": "0929-641-1309",
"picture": {
"large": "https://randomuser.me/api/portraits/women/48.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/48.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/48.jpg"
}
}
}
]
}
答案 0 :(得分:1)
如果您只是想按顺序对同一API发出10个请求(一个接一个,而不是并行),您可以这样做:
const got = require('got');
function runSequence(url, num) {
let cntr = 0;
let results = [];
return new Promise(function(resolve, reject) {
function checkDone(data) {
++cntr;
results.push(data);
if (cntr < num) {
next();
} else {
resolve(results);
}
}
function next() {
got(url).then(response => {
console.log(response.body);
checkDone(response.body);
}).catch(error => {
console.log(error.response.body);
checkDone(null);
});
}
next();
});
}
runSequence('https://randomuser.me/api/', 10).then(function(results) {
// access array of results here
});
如果不必一次一个地完成API调用,并且您可以同时将它们全部投放,那么您可以这样做:
function runParallel(url, num) {
let promises = [];
for (let i = 0; i < num; i++) {
promises.push(got(url));
}
return Promise.all(promises);
}
runParallel('https://randomuser.me/api/', 10).then(function(results) {
// access array of results here
});
注意:并行选项在第一个错误时中止,而此处显示的两个序列选项都会继续出错。要么可以改为其他行为。你没有说明你想要的东西。
这是一种稍微不同的运行序列的方式:
function runSequence(url, num) {
let cntr = 0;
let results = [];
function checkDone(data) {
++cntr;
results.push(data);
if (cntr < num) {
return next();
} else {
return results;
}
}
function next() {
return got(url).then(response => {
return checkDone(response.body);
}).catch(error => {
return checkDone(null);
});
}
return next();
}
这是一个用于重复一次异步操作N次的通用函数。您传入异步函数(返回一个promise),您希望它按顺序重复的次数,以及您是希望它在错误时继续还是在出错时中止。
// pass a function that returns a promise
function repeatSequence(fn, num, continueOnError) {
let cntr = 0;
let results = [];
checkDone(data) {
++cntr;
results.push(data);
if (cntr < num) {
return next();
} else {
return results;
}
}
function next() {
return fn().then(checkDone).catch(function(err) {
if (continueOnError) {
return checkDone(null);
} else {
// reject on error
throw err;
}
});
}
return next();
}
并且,如果您使用Bluebird Promise library,则可以使用Promise.mapSeries()
:
function repeatSequence(fn, num, continueOnError) {
var array = new Array(num);
return Promise.mapSeries(array, function () {
return fn().catch(function (err) {
if (continueOnError) {
return null;
} else {
throw (err);
}
});
});
}
或者,如果您不想要continueOnError
选项,它就会变为:
function repeatSequence(fn, num) {
var array = new Array(num);
return Promise.mapSeries(array, fn);
}
答案 1 :(得分:1)
我必须同意Bergi的观点,即我们不能将回调与承诺混在一起。尽管它们都是异步机制,但这两种结构中的每一种在本质上和哲学上都是不相同的。
然而,正如jfriend00指出的那样,主要的问题是&#34;回调&#34;在每一步都没有被召唤。在使用非承诺库时,这将是正确的解决方案。
<强>解决方案强>
请在下面找到我的修改。本质是:
async-q之类的端口可能会帮助您更好地利用现有库。
const got = require('got');
const async_q = require('async-q');
var tenOperations = [];
for(var i = 0; i < 10; i++) {
tenOperations.push(doRequest);
}
function doRequest() {
return got('https://randomuser.me/api/')
.then(response => {
console.log('resp', response.body);
return JSON.parse(response.body);
})
.catch(error => {
console.log('error', error.response.body);
return error.response.body;
});
}
async_q
.series(tenOperations)
.then (results => {
console.log('results', results);
})
.done();