Javascript Async承诺使用未知的异步值提供递归

Javascript Async承诺使用未知的异步值提供递归,javascript,asynchronous,recursion,promise,Javascript,Asynchronous,Recursion,Promise,我正在绞尽脑汁研究异步递归。我有很多承诺可以解决异步数据下载时的问题(由Promise.all组合而成)。但有时在我刚下载的数据中有到另一个数据的链接,必须下载(递归)。我想最好的解释是显示代码。注释用代码表示。 (我尝试过各种组合,但都没有效果。) var url=[]http://czyprzy.vdl.pl/file1.txt', 'http://czyprzy.vdl.pl/file2.txt', 'http://czyprzy.vdl.pl/file3.txt']; var urlsP

我正在绞尽脑汁研究异步递归。我有很多承诺可以解决异步数据下载时的问题(由Promise.all组合而成)。但有时在我刚下载的数据中有到另一个数据的链接,必须下载(递归)。我想最好的解释是显示代码。注释用代码表示。 (我尝试过各种组合,但都没有效果。)

var url=[]http://czyprzy.vdl.pl/file1.txt', 'http://czyprzy.vdl.pl/file2.txt', 'http://czyprzy.vdl.pl/file3.txt'];
var urlsPromise=[];
var secondPart=[];
第三部分变量=[];
函数urlContent(url,编号){
返回新承诺(函数(解析){
var dl=请求(url、函数(错误、响应、内容){
如果(错误| |响应状态代码>=400){
返回解析({number:number,url:url,错误:'err'});
}
如果(!err&&resp.statusCode==200){
if(content.indexOf('file')!==-1)//如果我们需要(希望:)的内容中有“file”,则通过递归下载此新文件
{
content=content.slice(content.indexOf('file')+4);
content=+content;//(稍后要传递的数字,以便我们知道正在处理的文件)
url='1〕http://czyprzy.vdl.pl/file“+content+”.txt“;/(我们创建新地址)
//push(urlContent(url,content));//这将在Promise.all(urlsPromise)之后执行,所以我们不能在这里执行递归(像那样)
secondPart.push(urlcont(url,content));//如果我们使用另一个promise数组将已解析的项放入该数组,那么一切都将正常工作—但只有在第一次使用之前,我们才需要添加另一个(第三部分)数组并使用另一个promise.all(第三部分)…等等等等…---问题是我不知道会有多少个文件,所以这意味着我不知道承诺有多少个“部分”。我所需要创建的,某种异步循环/递归将把我保存在这里,但我不知道如何正确地这样做,以便代码可以按正确的顺序运行
}
返回解析({number:number,url:url});//这将转到“urlsPromise”数组
}
});
});
}
如果(url.length!==0){
对于(var i=0;ifile4->file7->file10/-/file1内容:file4/-/file4内容:file7/-/file7内容:file10
//file2->file5->file8->file11/-/file2内容:file5/-/file5内容:file8/-/file8内容:file11
//file3->file6->file9->file12/-/file3内容:file6/-/file6内容:file9/-/file9内容:file12
////console.log输出如下所示:
// =======================================
//urlsPromise:
//[{编号:1,url:'http://czyprzy.vdl.pl/file4.txt' },
//{编号:2,url:'http://czyprzy.vdl.pl/file5.txt' },
//{编号:3,url:'http://czyprzy.vdl.pl/file6.txt' } ]
// =======================================
//第二部分:
//[{编号:4,url:'http://czyprzy.vdl.pl/file7.txt' },
//{编号:5,url:'http://czyprzy.vdl.pl/file8.txt' },
//{编号:6,url:'http://czyprzy.vdl.pl/file9.txt' } ]
// =======================================
//第三部分:
//[{号码:7,网址:'http://czyprzy.vdl.pl/file10.txt' },
//{编号:8,url:'http://czyprzy.vdl.pl/file11.txt' },
//{编号:9,url:'http://czyprzy.vdl.pl/file12.txt' } ]
//等等等等等等。。。

等待关键字可以大大简化这一过程。您不需要使用自递归函数。此演示使用随机大小的数组伪造服务器调用

//设置:创建一个包含随机数个选项的列表。
var sourceList=[];
var numItems=10+Math.floor(Math.random()*20);
对于(变量i=0;i=100){
完成=正确;
}
}
log(“获取所有项目”,集合);
}

poll()由于trincot-

当我直接问他这个问题时,他用时间和知识支持我,并给出了这个极好的答案

代码:

所有准备好下载的文件(链接)(URL数组中的3个起始文件)几乎立即下载(包含它们的数组上的同步循环-一个接一个,但非常快,因为我们只是以同步方式对它们进行迭代)

然后,当我们有了他们的
var urls = ['http://czyprzy.vdl.pl/file1.txt', 'http://czyprzy.vdl.pl/file2.txt', 'http://czyprzy.vdl.pl/file3.txt'];
var urlsPromise = [];
var secondPart = [];
var thirdPart = [];

function urlContent(url, number) {
  return new Promise(function (resolve) {
    var dl = request(url, function (err, resp, content) {
      if (err || resp.statusCode >= 400) {
        return resolve({number : number, url : url, error : 'err'});
      }
      if (!err && resp.statusCode == 200) {
        if (content.indexOf('file') !== -1) // if there is 'file' inside content we need (would like to :) download this new file by recursion
        {
            content = content.slice(content.indexOf('file') + 4);
            content =+ content; // (number to pass later on, so we know what file we are working on)
            url = 'http://czyprzy.vdl.pl/file' + content + '.txt'; // (we build new address)

            //urlsPromise.push(urlContent(url, content)); // this will perform AFTER Promise.all(urlsPromise) so we simply can't do recurention (like that) here
            secondPart.push(urlContent(url, content)); // if we use another promise array that put resolved items to that array everything will work just fine - but only till first time, then we would need to add another (thirdPart) array and use another Promise.all(thirdPart)... and so on and so on... --- the problem is I don't know how many files there will be, so it means I have no idea how many 'parts' for Promise.all I need to create, some kind of asynchronous loop/recursion would save me here, but I don't know how to do that properly so the code can run in proper order
        }
        return resolve({number : number, url : url}); // this goes to 'urlsPromise' array
      }
    });
  });
}

if (urls.length !== 0) {
  for (var i = 0; i < urls.length; i++)
  {urlsPromise.push(urlContent(urls[i], i + 1));}
}

Promise.all(urlsPromise).then(function(urlsPromise) {
  console.log('=======================================');
  console.log('urlsPromise:\n');
  console.log(urlsPromise); // some code/calculations here
}).then(function() {
  return Promise.all(secondPart).then(function(secondPart) {
    console.log('=======================================');
    console.log('secondPart:\n');
    console.log(secondPart); // some code/calculations here
    secondPart.forEach(function(item)
    {
        thirdPart.push(urlContent(item.url, item.number + 3));
    });
  });
}).then(function() {
  return Promise.all(thirdPart).then(function(thirdPart) {
    console.log('=======================================');
    console.log('thirdPart:\n');
    console.log(thirdPart); // some code/calculations here
  });
}).then(function()
{
    console.log();
    console.log('and so on and so on...');
});



//// files LINKING (those files do exist on live server - just for testing purposes):
// file1->file4->file7->file10  /-/ file1 content: file4 /-/ file4 content: file7 /-/ file7 content: file10
// file2->file5->file8->file11  /-/ file2 content: file5 /-/ file5 content: file8 /-/ file8 content: file11
// file3->file6->file9->file12  /-/ file3 content: file6 /-/ file6 content: file9 /-/ file9 content: file12



//// the console.log output looks like this:
// =======================================
// urlsPromise:

// [ { number: 1, url: 'http://czyprzy.vdl.pl/file4.txt' },
//   { number: 2, url: 'http://czyprzy.vdl.pl/file5.txt' },
//   { number: 3, url: 'http://czyprzy.vdl.pl/file6.txt' } ]
// =======================================
// secondPart:

// [ { number: 4, url: 'http://czyprzy.vdl.pl/file7.txt' },
//   { number: 5, url: 'http://czyprzy.vdl.pl/file8.txt' },
//   { number: 6, url: 'http://czyprzy.vdl.pl/file9.txt' } ]
// =======================================
// thirdPart:

// [ { number: 7, url: 'http://czyprzy.vdl.pl/file10.txt' },
//   { number: 8, url: 'http://czyprzy.vdl.pl/file11.txt' },
//   { number: 9, url: 'http://czyprzy.vdl.pl/file12.txt' } ]

// and so on and so on...
//// files LINKING (those files do exist on live server - just for testing purposes):
// file1->file4(AND file101)->file7->file10  /-/ file1 content: file4 /-/ file4 content: file7 /-/ file7 content: file10 /-/ file10 content: EMPTY /-/ file101 content: EMPTY
// file2->file5(AND file102)->file8->file11  /-/ file2 content: file5 /-/ file5 content: file8 /-/ file8 content: file11 /-/ file11 content: EMPTY /-/ file102 content: EMPTY
// file3->file6(AND file103)->file9->file12  /-/ file3 content: file6 /-/ file6 content: file9 /-/ file9 content: file12 /-/ file12 content: EMPTY /-/ file103 content: EMPTY

var urls = ['http://czyprzy.vdl.pl/file1.txt', 'http://czyprzy.vdl.pl/file2.txt', 'http://czyprzy.vdl.pl/file3.txt'];
var urlsPromise = [];

function requestPromise(url) {
    return new Promise(function(resolve, reject) {
        request(url, function (err, resp, content) {
            if (err || resp.statusCode != 200) reject(err || resp.statusCode);
            else resolve(content);
        });
    });
}

async function urlContent(url, number) {
  var arr = [];
  let content = await requestPromise(url);

  while (content.indexOf(';') !== -1)
  {
    var semiColon = content.indexOf(';');
var fileLink = content.slice(content.indexOf('file'), semiColon + 1);
content = content.replace(fileLink, ''); // we need to remove the file link so we won't iterate over it again, we will add to the array only new links
var fileLinkNumber = fileLink.replace('file', '');
fileLinkNumber = fileLinkNumber.replace(';', '');
fileLinkNumber =+ fileLinkNumber;
url = 'http://czyprzy.vdl.pl/file' + fileLinkNumber + '.txt'; // we build new address
arr.push({url, fileLinkNumber});
}
if (content.indexOf('file') !== -1)
{
var fileLinkNumber = content.slice(content.indexOf('file') + 4);
fileLinkNumber =+ fileLinkNumber;
  url = 'http://czyprzy.vdl.pl/file' + fileLinkNumber + '.txt';
  arr.push({url, fileLinkNumber});
}
var newArr = arr.map(function(item)
{
return urlContent(item.url, item.fileLinkNumber); // return IS important here
});
return [].concat(arr, ...await Promise.all(newArr));
}

async function doing() {
    let urlsPromise = [];
    for (let i = 0; i < urls.length; i++) {
        urlsPromise.push(urlContent(urls[i], i + 1));
    }
    let results = [].concat(...await Promise.all(urlsPromise)); // flatten the array of arrays
    console.log(results);
}

//// this is only to show Promise.all chaining - so you can do async loop, and then wait for some another async data - in proper chain.

var test_a = ['http://czyprzy.vdl.pl/css/1.css', 'http://czyprzy.vdl.pl/css/2.css', 'http://czyprzy.vdl.pl/css/cssa/1a.css', 'http://czyprzy.vdl.pl/css/cssa/2a.css'];
var promisesTest_a = [];

function requestStyle(url)
{
return new Promise(function(resolve, reject)
{
request(url, function(error, response, content)
{
if (response.statusCode === 200 && !error)
{resolve(content);}
else
{reject(error);}
});
});
}

for (var i = 0; i < test_a.length; i++)
{promisesTest_a.push(requestStyle(test_a[i]));}

Promise.all(promisesTest_a).then(function(promisesTest_a)
{
   console.log(promisesTest_a);
}).then(function()
{
   console.log('\nNow we start with @imports...\n');
}).then(function()
{
   return doing();
}).then(function()
{
   console.log('ALL DONE!');
});
var arr = [];
var array1 = ['one', 'two', 'three']
var array2 = [['four', 'five', ['six', 'seven']], 'eight', 'nine', 'ten'];
arr = array1.concat(array2);
console.log(arr); // it does not flattern the array - it just concatenate them (join them together)
console.log('---');
// however
arr = array1.concat(...array2);
console.log(arr); // notice the [...] - as you can see it flatern the array - 'four' and 'five' are pull out of an array - think of it as level up :) remember that it pull up WHOLE array that is deeper - so 'six' and 'seven' are now 1 level deep (up from 2 levels deep, but still in another array).
console.log('---');
// so
arr = [].concat(...arr);
console.log(arr); // hurrrray our array is flat (single array without nested elements)
console.log();