javascript 中的递归 Promise
Recursive Promise in javascript
我正在写一个 Javascript Promise
来找到 link.
的最终重定向 URL
我正在做的是使用 XMLHttpRequest
在 Promise
中发出 HEAD
请求。然后,在加载时,检查 300 范围内的某些东西的 HTTP 状态,或者它是否有一个 responseURL
附加到对象并且 url 与它是单手的不同。
如果这两个都不成立,我resolve(url)
。否则,我在响应 URL 和 resolve()
.
上递归调用 getRedirectUrl()
这是我的代码:
function getRedirectUrl(url, maxRedirects) {
maxRedirects = maxRedirects || 0;
if (maxRedirects > 10) {
throw new Error("Redirected too many times.");
}
var xhr = new XMLHttpRequest();
var p = new Promise(function (resolve) {
xhr.onload = function () {
var redirectsTo;
if (this.status < 400 && this.status >= 300) {
redirectsTo = this.getResponseHeader("Location");
} else if (this.responseURL && this.responseURL != url) {
redirectsTo = this.responseURL;
}
if (redirectsTo) {
// check that redirect address doesn't redirect again
// **problem line**
p.then(function () { self.getRedirectUrl(redirectsTo, maxRedirects + 1); });
resolve();
} else {
resolve(url);
}
}
xhr.open('HEAD', url, true);
xhr.send();
});
return p;
}
然后为了使用这个函数我做了类似的事情:
getRedirectUrl(myUrl).then(function (url) { ... });
问题是 getRedirectUrl
中的 resolve();
会在调用 getRedirectUrl
递归调用之前从调用函数调用 then()
,此时, URL 是 undefined
.
我试过了,而不是 p.then(...getRedirectUrl...)
做 return self.getRedirectUrl(...)
但这永远不会解决。
我的猜测是我正在使用的模式(我基本上是临时想到的)完全不正确。
问题是 return 来自 getRedirectUrl()
的承诺需要包含整个逻辑链才能到达 URL。您只是 return 对第一个请求的承诺。您在函数中使用的 .then()
没有执行任何操作。
解决这个问题:
创建一个解析为 redirectUrl
重定向的承诺,否则 null
:
function getRedirectsTo(xhr) {
if (xhr.status < 400 && xhr.status >= 300) {
return xhr.getResponseHeader("Location");
}
if (xhr.responseURL && xhr.responseURL != url) {
return xhr.responseURL;
}
return null;
}
var p = new Promise(function (resolve) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(getRedirectsTo(xhr));
};
xhr.open('HEAD', url, true);
xhr.send();
});
在 that 上使用 .then()
到 return 递归调用,或不使用,视需要而定:
return p.then(function (redirectsTo) {
return redirectsTo
? getRedirectUrl(redirectsTo, redirectCount+ 1)
: url;
});
完整解决方案:
function getRedirectsTo(xhr) {
if (xhr.status < 400 && xhr.status >= 300) {
return xhr.getResponseHeader("Location");
}
if (xhr.responseURL && xhr.responseURL != url) {
return xhr.responseURL;
}
return null;
}
function getRedirectUrl(url, redirectCount) {
redirectCount = redirectCount || 0;
if (redirectCount > 10) {
throw new Error("Redirected too many times.");
}
return new Promise(function (resolve) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(getRedirectsTo(xhr));
};
xhr.open('HEAD', url, true);
xhr.send();
})
.then(function (redirectsTo) {
return redirectsTo
? getRedirectUrl(redirectsTo, redirectCount + 1)
: url;
});
}
请查看下面的示例,它将 return factorial
给定的数字,就像我们在许多编程语言中所做的那样。
我已经使用 JavaScript
承诺实现了以下示例。
let code = (function(){
let getFactorial = n =>{
return new Promise((resolve,reject)=>{
if(n<=1){
resolve(1);
}
resolve(
getFactorial(n-1).then(fact => {
return fact * n;
})
)
});
}
return {
factorial: function(number){
getFactorial(number).then(
response => console.log(response)
)
}
}
})();
code.factorial(5);
code.factorial(6);
code.factorial(7);
这是简化的解决方案:
const recursiveCall = (index) => {
return new Promise((resolve) => {
console.log(index);
if (index < 3) {
return resolve(recursiveCall(++index))
} else {
return resolve()
}
})
}
recursiveCall(0).then(() => console.log('done'));
如果您处于支持 async
/await
的环境中(几乎所有现代环境都支持),您可以编写一个看起来更像递归的 async function
我们都知道和喜爱的函数模式。由于 XMLHttpRequest
仅通过 load
事件检索值(而不是暴露 Promise
本身)的性质,不可能完全避免 Promise
,但是递归进行调用的函数的性质应该看起来很熟悉。
比我最初写这个问题时多了四年的 JavaScript 经验,我稍微清理了代码,但它的工作方式基本相同。
// creates a simple Promise that resolves the xhr once it has finished loading
function createXHRPromise(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// addEventListener('load', ...) is basically the same as setting
// xhr.onload, but is better practice
xhr.addEventListener('load', () => resolve(xhr));
// throw in some error handling so that the calling function
// won't hang
xhr.addEventListener('error', reject);
xhr.addEventListener('abort', reject);
xhr.open('HEAD', url, true);
xhr.send();
});
}
async function getRedirectUrl(url, maxRetries = 10) {
if (maxRetries <= 0) {
throw new Error('Redirected too many times');
}
const xhr = await createXHRPromise(url);
if (xhr.status >= 300 && xhr.status < 400) {
return getRedirectUrl(xhr.getResponseHeader("Location"), maxRetries - 1);
} else if (xhr.responseURL && xhr.responseURL !== url) {
return getRedirectUrl(xhr.responseURL, maxRetries - 1);
}
return url;
}
async
/await
的简要说明
async function
是 Promise
的语法糖
await
是 Promise.then()
的语法糖
return
在 async function
中是 resolve()
的语法糖
async function
中的 throw
是 reject()
的语法糖
如果 async function
returns 另一个 async function
调用或 Promise
,function/promise 将在原始调用解析之前解析,完全相同在 Promise
模式中解析 Promise
的方式。
因此,您可以调用 getRedirectUrl(someUrl).then(...).catch(...)
与原始问题完全相同的方式。
可能应该注意的是,使用 XHR 解析重定向的 URL 对于任何不包含正确 CORS header.[=41= 的 URL 都会失败]
作为额外的好处,async/await 使迭代方法变得微不足道。
async function getRedirectUrl(url, maxRetries = 10) {
for (let i = 0; i < maxRetries; i++) {
const xhr = await createXHRPromise(url);
if (xhr.status >= 300 && xhr.status < 400) {
url = xhr.getResponseHeader("Location");
} else if (xhr.responseURL && xhr.responseURL !== url) {
url = xhr.responseURL;
} else {
return url;
}
}
throw new Error('Redirected too many times');
}
另一个注意事项:现代浏览器有一个 fetch()
函数,它的作用与 createXHRPromise()
的作用基本相同,但用途更广。它在节点中不受支持,但有一个名为 node-fetch
.
的 npm 包
下面有两个函数:
- _getRedirectUrl - 这是一个 setTimeout 对象模拟,用于查找重定向的单步查找 URL(这相当于您的 XMLHttpRequest HEAD 请求的单个实例)
- getRedirectUrl - 这是递归调用承诺查找重定向 URL
秘诀是子 Promise,其成功完成将触发父 Promise 对 resolve() 的调用。
function _getRedirectUrl( url ) {
return new Promise( function (resolve) {
const redirectUrl = {
"https://mary" : "https://had",
"https://had" : "https://a",
"https://a" : "https://little",
"https://little" : "https://lamb",
}[ url ];
setTimeout( resolve, 500, redirectUrl || url );
} );
}
function getRedirectUrl( url ) {
return new Promise( function (resolve) {
console.log("* url: ", url );
_getRedirectUrl( url ).then( function (redirectUrl) {
// console.log( "* redirectUrl: ", redirectUrl );
if ( url === redirectUrl ) {
resolve( url );
return;
}
getRedirectUrl( redirectUrl ).then( resolve );
} );
} );
}
function run() {
let inputUrl = $( "#inputUrl" ).val();
console.log( "inputUrl: ", inputUrl );
$( "#inputUrl" ).prop( "disabled", true );
$( "#runButton" ).prop( "disabled", true );
$( "#outputLabel" ).text( "" );
getRedirectUrl( inputUrl )
.then( function ( data ) {
console.log( "output: ", data);
$( "#inputUrl" ).prop( "disabled", false );
$( "#runButton" ).prop( "disabled", false );
$( "#outputLabel").text( data );
} );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Input:
<select id="inputUrl">
<option value="https://mary">https://mary</option>
<option value="https://had">https://had</option>
<option value="https://a">https://a</option>
<option value="https://little">https://little</option>
<option value="https://lamb">https://lamb</option>
</select>
Output:
<label id="outputLabel"></label>
<button id="runButton" onclick="run()">Run</button>
作为递归 Promises 的另一个例子,我用它来解决迷宫问题。 Solve()
函数被递归调用以在迷宫的解决方案中前进一步,否则在遇到死胡同时回溯。 setTimeout
函数用于将解的动画设置为每帧100ms(即10hz帧率)。
const MazeWidth = 9
const MazeHeight = 9
let Maze = [
"# #######",
"# # #",
"# ### # #",
"# # # #",
"# # # ###",
"# # # #",
"# ### # #",
"# # #",
"####### #"
].map(line => line.split(''));
const Wall = '#'
const Free = ' '
const SomeDude = '*'
const StartingPoint = [1, 0]
const EndingPoint = [7, 8]
function PrintDaMaze()
{
//Maze.forEach(line => console.log(line.join('')))
let txt = Maze.reduce((p, c) => p += c.join('') + '\n', '')
let html = txt.replace(/[*]/g, c => '<font color=red>*</font>')
$('#mazeOutput').html(html)
}
function Solve(X, Y) {
return new Promise( function (resolve) {
if ( X < 0 || X >= MazeWidth || Y < 0 || Y >= MazeHeight ) {
resolve( false );
return;
}
if ( Maze[Y][X] !== Free ) {
resolve( false );
return;
}
setTimeout( function () {
// Make the move (if it's wrong, we will backtrack later)
Maze[Y][X] = SomeDude;
PrintDaMaze()
// Check if we have reached our goal.
if (X == EndingPoint[0] && Y == EndingPoint[1]) {
resolve(true);
return;
}
// Recursively search for our goal.
Solve(X - 1, Y)
.then( function (solved) {
if (solved) return Promise.resolve(solved);
return Solve(X + 1, Y);
} )
.then( function (solved) {
if (solved) return Promise.resolve(solved);
return Solve(X, Y - 1);
} )
.then( function (solved) {
if (solved) return Promise.resolve(solved);
return Solve(X, Y + 1);
} )
.then( function (solved) {
if (solved) {
resolve(true);
return;
}
// Backtrack
setTimeout( function () {
Maze[Y][X] = Free;
PrintDaMaze()
resolve(false);
}, 100);
} );
}, 100 );
} );
}
Solve(StartingPoint[0], StartingPoint[1])
.then( function (solved) {
if (solved) {
console.log("Solved!")
PrintDaMaze()
}
else
{
console.log("Cannot solve. :-(")
}
} );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<pre id="mazeOutput">
</pre>
请检查下面的示例以了解 javascript/typescript 中的递归 Promise,直到数字递增到大于 13 时才会解析 Promise。
下面的代码适用于 typescript 并稍微修改一下 javascript。
async iterate(number: number): Promise<any> {
return new Promise((resolve, reject) => {
let number = 0;
if (number > 13) {
// recursive terminate condition
resolve(number);
return;
} else {
number = number + 1;
// recursive call
this.iterate(number).then(resolve);
}
});
}
this.iterate().then((resolvedData: any) => {
// wait until number is not greater than 13
console.log(resolvedData);
});
如果您有带异步调用的嵌套数组结构,此解决方案(基于以前的答案)可能会有所帮助。该示例为它在(可能)嵌套数组中找到的每个值运行一个 setTimeout() 并在完成所有这些值时解析:
const recursiveCall = (obj) => {
return new Promise((resolve) => {
if(obj instanceof Array){
let cnt = obj.length;
obj.forEach(el => {
recursiveCall(el)
.then(() => {
if(!--cnt)return resolve();
})
});
} else {
setTimeout(() => {
console.log(obj);
return resolve();
}, obj);
}
})
}
recursiveCall([100,50,[10,[200, 300],30],1]).then(() => console.log('done'));
>1
>10
>30
>50
>100
>200
>300
>done
我正在写一个 Javascript Promise
来找到 link.
我正在做的是使用 XMLHttpRequest
在 Promise
中发出 HEAD
请求。然后,在加载时,检查 300 范围内的某些东西的 HTTP 状态,或者它是否有一个 responseURL
附加到对象并且 url 与它是单手的不同。
如果这两个都不成立,我resolve(url)
。否则,我在响应 URL 和 resolve()
.
getRedirectUrl()
这是我的代码:
function getRedirectUrl(url, maxRedirects) {
maxRedirects = maxRedirects || 0;
if (maxRedirects > 10) {
throw new Error("Redirected too many times.");
}
var xhr = new XMLHttpRequest();
var p = new Promise(function (resolve) {
xhr.onload = function () {
var redirectsTo;
if (this.status < 400 && this.status >= 300) {
redirectsTo = this.getResponseHeader("Location");
} else if (this.responseURL && this.responseURL != url) {
redirectsTo = this.responseURL;
}
if (redirectsTo) {
// check that redirect address doesn't redirect again
// **problem line**
p.then(function () { self.getRedirectUrl(redirectsTo, maxRedirects + 1); });
resolve();
} else {
resolve(url);
}
}
xhr.open('HEAD', url, true);
xhr.send();
});
return p;
}
然后为了使用这个函数我做了类似的事情:
getRedirectUrl(myUrl).then(function (url) { ... });
问题是 getRedirectUrl
中的 resolve();
会在调用 getRedirectUrl
递归调用之前从调用函数调用 then()
,此时, URL 是 undefined
.
我试过了,而不是 p.then(...getRedirectUrl...)
做 return self.getRedirectUrl(...)
但这永远不会解决。
我的猜测是我正在使用的模式(我基本上是临时想到的)完全不正确。
问题是 return 来自 getRedirectUrl()
的承诺需要包含整个逻辑链才能到达 URL。您只是 return 对第一个请求的承诺。您在函数中使用的 .then()
没有执行任何操作。
解决这个问题:
创建一个解析为 redirectUrl
重定向的承诺,否则 null
:
function getRedirectsTo(xhr) {
if (xhr.status < 400 && xhr.status >= 300) {
return xhr.getResponseHeader("Location");
}
if (xhr.responseURL && xhr.responseURL != url) {
return xhr.responseURL;
}
return null;
}
var p = new Promise(function (resolve) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(getRedirectsTo(xhr));
};
xhr.open('HEAD', url, true);
xhr.send();
});
在 that 上使用 .then()
到 return 递归调用,或不使用,视需要而定:
return p.then(function (redirectsTo) {
return redirectsTo
? getRedirectUrl(redirectsTo, redirectCount+ 1)
: url;
});
完整解决方案:
function getRedirectsTo(xhr) {
if (xhr.status < 400 && xhr.status >= 300) {
return xhr.getResponseHeader("Location");
}
if (xhr.responseURL && xhr.responseURL != url) {
return xhr.responseURL;
}
return null;
}
function getRedirectUrl(url, redirectCount) {
redirectCount = redirectCount || 0;
if (redirectCount > 10) {
throw new Error("Redirected too many times.");
}
return new Promise(function (resolve) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(getRedirectsTo(xhr));
};
xhr.open('HEAD', url, true);
xhr.send();
})
.then(function (redirectsTo) {
return redirectsTo
? getRedirectUrl(redirectsTo, redirectCount + 1)
: url;
});
}
请查看下面的示例,它将 return factorial
给定的数字,就像我们在许多编程语言中所做的那样。
我已经使用 JavaScript
承诺实现了以下示例。
let code = (function(){
let getFactorial = n =>{
return new Promise((resolve,reject)=>{
if(n<=1){
resolve(1);
}
resolve(
getFactorial(n-1).then(fact => {
return fact * n;
})
)
});
}
return {
factorial: function(number){
getFactorial(number).then(
response => console.log(response)
)
}
}
})();
code.factorial(5);
code.factorial(6);
code.factorial(7);
这是简化的解决方案:
const recursiveCall = (index) => {
return new Promise((resolve) => {
console.log(index);
if (index < 3) {
return resolve(recursiveCall(++index))
} else {
return resolve()
}
})
}
recursiveCall(0).then(() => console.log('done'));
如果您处于支持 async
/await
的环境中(几乎所有现代环境都支持),您可以编写一个看起来更像递归的 async function
我们都知道和喜爱的函数模式。由于 XMLHttpRequest
仅通过 load
事件检索值(而不是暴露 Promise
本身)的性质,不可能完全避免 Promise
,但是递归进行调用的函数的性质应该看起来很熟悉。
比我最初写这个问题时多了四年的 JavaScript 经验,我稍微清理了代码,但它的工作方式基本相同。
// creates a simple Promise that resolves the xhr once it has finished loading
function createXHRPromise(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// addEventListener('load', ...) is basically the same as setting
// xhr.onload, but is better practice
xhr.addEventListener('load', () => resolve(xhr));
// throw in some error handling so that the calling function
// won't hang
xhr.addEventListener('error', reject);
xhr.addEventListener('abort', reject);
xhr.open('HEAD', url, true);
xhr.send();
});
}
async function getRedirectUrl(url, maxRetries = 10) {
if (maxRetries <= 0) {
throw new Error('Redirected too many times');
}
const xhr = await createXHRPromise(url);
if (xhr.status >= 300 && xhr.status < 400) {
return getRedirectUrl(xhr.getResponseHeader("Location"), maxRetries - 1);
} else if (xhr.responseURL && xhr.responseURL !== url) {
return getRedirectUrl(xhr.responseURL, maxRetries - 1);
}
return url;
}
async
/await
的简要说明
async function
是Promise
的语法糖
await
是Promise.then()
的语法糖
return
在async function
中是resolve()
的语法糖
throw
是reject()
的语法糖
async function
中的 如果 async function
returns 另一个 async function
调用或 Promise
,function/promise 将在原始调用解析之前解析,完全相同在 Promise
模式中解析 Promise
的方式。
因此,您可以调用 getRedirectUrl(someUrl).then(...).catch(...)
与原始问题完全相同的方式。
可能应该注意的是,使用 XHR 解析重定向的 URL 对于任何不包含正确 CORS header.[=41= 的 URL 都会失败]
作为额外的好处,async/await 使迭代方法变得微不足道。
async function getRedirectUrl(url, maxRetries = 10) {
for (let i = 0; i < maxRetries; i++) {
const xhr = await createXHRPromise(url);
if (xhr.status >= 300 && xhr.status < 400) {
url = xhr.getResponseHeader("Location");
} else if (xhr.responseURL && xhr.responseURL !== url) {
url = xhr.responseURL;
} else {
return url;
}
}
throw new Error('Redirected too many times');
}
另一个注意事项:现代浏览器有一个 fetch()
函数,它的作用与 createXHRPromise()
的作用基本相同,但用途更广。它在节点中不受支持,但有一个名为 node-fetch
.
下面有两个函数:
- _getRedirectUrl - 这是一个 setTimeout 对象模拟,用于查找重定向的单步查找 URL(这相当于您的 XMLHttpRequest HEAD 请求的单个实例)
- getRedirectUrl - 这是递归调用承诺查找重定向 URL
秘诀是子 Promise,其成功完成将触发父 Promise 对 resolve() 的调用。
function _getRedirectUrl( url ) {
return new Promise( function (resolve) {
const redirectUrl = {
"https://mary" : "https://had",
"https://had" : "https://a",
"https://a" : "https://little",
"https://little" : "https://lamb",
}[ url ];
setTimeout( resolve, 500, redirectUrl || url );
} );
}
function getRedirectUrl( url ) {
return new Promise( function (resolve) {
console.log("* url: ", url );
_getRedirectUrl( url ).then( function (redirectUrl) {
// console.log( "* redirectUrl: ", redirectUrl );
if ( url === redirectUrl ) {
resolve( url );
return;
}
getRedirectUrl( redirectUrl ).then( resolve );
} );
} );
}
function run() {
let inputUrl = $( "#inputUrl" ).val();
console.log( "inputUrl: ", inputUrl );
$( "#inputUrl" ).prop( "disabled", true );
$( "#runButton" ).prop( "disabled", true );
$( "#outputLabel" ).text( "" );
getRedirectUrl( inputUrl )
.then( function ( data ) {
console.log( "output: ", data);
$( "#inputUrl" ).prop( "disabled", false );
$( "#runButton" ).prop( "disabled", false );
$( "#outputLabel").text( data );
} );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Input:
<select id="inputUrl">
<option value="https://mary">https://mary</option>
<option value="https://had">https://had</option>
<option value="https://a">https://a</option>
<option value="https://little">https://little</option>
<option value="https://lamb">https://lamb</option>
</select>
Output:
<label id="outputLabel"></label>
<button id="runButton" onclick="run()">Run</button>
作为递归 Promises 的另一个例子,我用它来解决迷宫问题。 Solve()
函数被递归调用以在迷宫的解决方案中前进一步,否则在遇到死胡同时回溯。 setTimeout
函数用于将解的动画设置为每帧100ms(即10hz帧率)。
const MazeWidth = 9
const MazeHeight = 9
let Maze = [
"# #######",
"# # #",
"# ### # #",
"# # # #",
"# # # ###",
"# # # #",
"# ### # #",
"# # #",
"####### #"
].map(line => line.split(''));
const Wall = '#'
const Free = ' '
const SomeDude = '*'
const StartingPoint = [1, 0]
const EndingPoint = [7, 8]
function PrintDaMaze()
{
//Maze.forEach(line => console.log(line.join('')))
let txt = Maze.reduce((p, c) => p += c.join('') + '\n', '')
let html = txt.replace(/[*]/g, c => '<font color=red>*</font>')
$('#mazeOutput').html(html)
}
function Solve(X, Y) {
return new Promise( function (resolve) {
if ( X < 0 || X >= MazeWidth || Y < 0 || Y >= MazeHeight ) {
resolve( false );
return;
}
if ( Maze[Y][X] !== Free ) {
resolve( false );
return;
}
setTimeout( function () {
// Make the move (if it's wrong, we will backtrack later)
Maze[Y][X] = SomeDude;
PrintDaMaze()
// Check if we have reached our goal.
if (X == EndingPoint[0] && Y == EndingPoint[1]) {
resolve(true);
return;
}
// Recursively search for our goal.
Solve(X - 1, Y)
.then( function (solved) {
if (solved) return Promise.resolve(solved);
return Solve(X + 1, Y);
} )
.then( function (solved) {
if (solved) return Promise.resolve(solved);
return Solve(X, Y - 1);
} )
.then( function (solved) {
if (solved) return Promise.resolve(solved);
return Solve(X, Y + 1);
} )
.then( function (solved) {
if (solved) {
resolve(true);
return;
}
// Backtrack
setTimeout( function () {
Maze[Y][X] = Free;
PrintDaMaze()
resolve(false);
}, 100);
} );
}, 100 );
} );
}
Solve(StartingPoint[0], StartingPoint[1])
.then( function (solved) {
if (solved) {
console.log("Solved!")
PrintDaMaze()
}
else
{
console.log("Cannot solve. :-(")
}
} );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<pre id="mazeOutput">
</pre>
请检查下面的示例以了解 javascript/typescript 中的递归 Promise,直到数字递增到大于 13 时才会解析 Promise。
下面的代码适用于 typescript 并稍微修改一下 javascript。
async iterate(number: number): Promise<any> {
return new Promise((resolve, reject) => {
let number = 0;
if (number > 13) {
// recursive terminate condition
resolve(number);
return;
} else {
number = number + 1;
// recursive call
this.iterate(number).then(resolve);
}
});
}
this.iterate().then((resolvedData: any) => {
// wait until number is not greater than 13
console.log(resolvedData);
});
如果您有带异步调用的嵌套数组结构,此解决方案(基于以前的答案)可能会有所帮助。该示例为它在(可能)嵌套数组中找到的每个值运行一个 setTimeout() 并在完成所有这些值时解析:
const recursiveCall = (obj) => {
return new Promise((resolve) => {
if(obj instanceof Array){
let cnt = obj.length;
obj.forEach(el => {
recursiveCall(el)
.then(() => {
if(!--cnt)return resolve();
})
});
} else {
setTimeout(() => {
console.log(obj);
return resolve();
}, obj);
}
})
}
recursiveCall([100,50,[10,[200, 300],30],1]).then(() => console.log('done'));
>1
>10
>30
>50
>100
>200
>300
>done