gpt4 book ai didi

javascript - promise 未返回预期值

转载 作者:太空宇宙 更新时间:2023-11-04 03:22:50 24 4
gpt4 key购买 nike

我一直在学习 Promise,但我有一个问题。我有一个名为 getNumber 的函数,它返回一个数字数组(为了理解)。我使用该函数迭代该数组并对每个值发出 http 请求(使用 setTimeout 在调用之间进行延迟)

然后我想使用在 then 函数中收集的信息,但它给了我一个“未定义错误”。显然这里有问题,但我看不到它。你知道我该如何解决这个问题以及出了什么问题吗?

var getNumbers  = () => {
return new Promise(function(resolve, reject) {

console.log("In function getNumbers");
var data = [1,2,3,4,5,6,7,8,9];
resolve(data);
});
};


getNumbers()

.then(numbersArray => {
//Supposed to return array of posts title
return numbersArray.map(number => {
console.log("Reading number" + number);

setTimeout(() => {
//make a http request
return getHtml("https://jsonplaceholder.typicode.com/posts/"+number)
.then(function(post) {
return post.title;
})

}, 10000);//make a request each ten seconds
});
})
.then(postTitlesArray => {
//Shows array of undefined
console.log(postTitlesArray)

});



function getHtml(webUrl) {
return fetch(webUrl)
.then(function(res) {
return res.json();
});
}

最佳答案

有几个概念性的事情阻碍了你做你想做的事的方法。

首先,.map() 是同步的。这意味着它会运行直至完成,并且不会等待任何异步操作完成。

其次,setTimeout() 是非阻塞的。它只是在未来的某个时间安排一个计时器,然后您的 .map() 回调立即返回,不返回任何内容。

所以,你的方法根本行不通。

从您的评论来看,您想要完成的任务似乎是在循环中进行一堆网络调用,但在它们之间设置延迟,这样您就不会受到速率限制。有很多方法可以做到这一点。

要实现这一点,您需要两个基本概念:

  1. 使异步操作按顺序进行,以便在前一个操作完成之前不会启动下一个操作。

  2. 在开始下一个 promise 之前,设置一个适合 promise 的延迟。

我将首先展示使用 async/await 的 ES7 方法,因为它在概念上看起来可能是最简单的。

使用async/await排序异步数组访问

function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}

getNumbers().then(async function(numbersArray) {
//Supposed to return array of posts title
let results = [];
let delayT = 0; // first delay is zero
for (let number of numbersArray) {
console.log("Reading number" + number);
let r = await delay(delayT).then(() => {
delayT = 10 * 1000; // 10 seconds for subsequent delays
return getHtml("https://jsonplaceholder.typicode.com/posts/"+number).then(function(post) {
return post.title;
});
});
results.push(r);
}
return results;
});

使用.reduce()排序异步数组访问

如果您想在没有 async/await 的情况下完成此操作,那么您可以使用 .reduce() 设计模式来对数组的异步迭代进行排序:

function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}

getNumbers().then(numbersArray => {
//Supposed to return array of posts title
let results = [];
let delayT = 0; // first delay is zero
return numersArray.reduce((p, number) => {
return p.then(() => {
return delay(delayT).then(() => {
delayT = 10 * 1000; // 10 seconds for subsequent delays
return getHtml("https://jsonplaceholder.typicode.com/posts/"+number).then(function(post) {
results.push(post.title);
});
});
});
}, Promise.resolve()).then(() => {
// make array of results be the resolved value of the returned promise
return results;
});
});

请注意,这两种算法都经过编码,不会延迟第一个操作,因为您可能不需要这样做,因此它只会在连续操作之间延迟。

<小时/>

按照编码,它们是在 Promise.all() 之后建模的,如果您的任何 getHtml() 调用被拒绝,它们就会拒绝。如果你想返回所有结果,即使有些结果拒绝,那么你可以更改:

return getHtml(...).then(...)

return getHtml(...).then(...).catch(err => null);

对于任何失败的结果,它将把 null 放入返回的数组中,或者如果您想记录错误,您可以使用:

return getHtml(...).then(...).catch(err => {
console.log(err);
return null;
});
<小时/>

通用辅助函数

而且,由于这是一个有点通用的问题,这里有一个通用的辅助函数,它允许您迭代一个数组,对数组中的每个项目调用异步操作并将所有结果累积到一个数组中:

// Iterate through an array in sequence with optional delay between each async operation
// Returns a promise, resolved value is array of results
async iterateArrayAsync(array, fn, opts = {}) {
const options = Object.assign({
continueOnError: true,
delayBetweenAsyncOperations: 0,
errPlaceHolder: null
}, opts);
const results = [];
let delayT = 0; // no delay on first iteration
for (let item of array) {
results.push(await delay(delayT).then(() => {
return fn(item);
}).catch(err => {
console.log(err);
if (options.continueOnError) {
// keep going on errors, let options.errPlaceHolder be result for an error
return options.errPlaceHolder;
} else {
// abort processing on first error, will reject the promise
throw err;
}
}));
delayT = options.delayBetweenAsyncOperations; // set delay between requests
}
return results;
}

它接受允许您 continueOnError 的选项,允许您设置每个异步操作之间的延迟,并允许您控制任何失败操作的结果数组中的占位符(仅在设置了 continueOnError 时使用)。所有选项都是可选的。

关于javascript - promise 未返回预期值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48255970/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com