使用 array.map、promises 和 setTimeout 更新数组
Posted
技术标签:
【中文标题】使用 array.map、promises 和 setTimeout 更新数组【英文标题】:Using array.map, promises, and setTimeout to update an array 【发布时间】:2019-02-01 11:21:56 【问题描述】:我希望遍历用户数组(仅设置 id 属性),每两秒使用每个 id 调用一个端点,并将响应中的关联用户名存储到更新数组。
例如更新 [ id: 1 ]
到 [ id: 1, name: "Leanne Graham" ]
这是我的代码:
const axios = require('axios');
const users = [ id: 1 , id: 2 , id: 3 ];
function addNameToUser(user)
return new Promise((resolve) =>
axios.get(`https://jsonplaceholder.typicode.com/users/$user.id`)
.then(response =>
user.name = response.data.name
resolve(user);
);
)
const requests = users.map((user, index) =>
setTimeout(() =>
return addNameToUser(user);
, index * 2000);
);
Promise.all(requests).then((updatedArr) =>
console.log(updatedArr);
);
没有setTimeout
,一切都很好,但重要的是我只每两秒发送一个请求。所以对于三个用户,我想在六秒左右后从我的Promise.all
日志中看到结果。
值得注意:这不是我正在处理的实际问题,而是我能想出的最简单的例子来帮助突出这个问题。
【问题讨论】:
***.com/questions/23803743/… 您的意思是请求 user1 并等待 2 秒,请求 user1 并等待 2 秒,...或请求 user1 结束并等待 2 秒,... 【参考方案1】:据我了解,您问题的核心是如何将您的处理间隔 2 秒,对吧?
const users = [ id: 1 , id: 2 , id: 3 ];
/* throttledProcess is a function that does your processing spaced by the given interval millisecond */
const throttledProcess = (items, interval) =>
if (items.length == 0) // stop when there's no more items to process
console.log('ALL DONE')
return
console.log('PROCESSING', items[0], Date()) // this is where your http call/update/etc takes place
setTimeout(() => throttledProcess(items.slice(1), interval), // wrap in an arrow function to defer evaluation
interval)
throttledProcess(users, 2000) // run process. shows output every 2 seconds
运行此代码,每 2 秒,它将注销正在处理的用户。
希望这会有所帮助。 干杯,
【讨论】:
【参考方案2】:您需要从地图的回调中返回一个 Promise。由于此承诺将由setTimeout()
解决,因此我们将使用Promise constructor。
已解决的超时承诺应返回 Axios 承诺,该承诺将在解决时返回结果。
注意:由于 Axios 返回一个 Promise,我们不需要用另一个 Promise 构造函数包装它。见What is the explicit promise construction antipattern and how do I avoid it?问答。
const users = [ id: 1 , id: 2 , id: 3 ];
const addNameToUser = (user) =>
axios.get(`https://jsonplaceholder.typicode.com/users/$user.id`)
.then(( data ) => (
...user,
name: data.name
));
const requests = users.map((user, index) =>
new Promise(resolve =>
setTimeout(() => resolve(addNameToUser(user)), index * 2000)
));
Promise.all(requests).then((updatedArr) =>
console.log(updatedArr);
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
【讨论】:
以上是关于使用 array.map、promises 和 setTimeout 更新数组的主要内容,如果未能解决你的问题,请参考以下文章
使用 Array.map 时嵌套承诺,使用 Promise.all 但仍然无法正常工作
处理 Array#map 中的 async/await 中的错误(拒绝)
即使 .map 循环通过数组的所有索引,也无法在我的 React 应用程序中的 array.map 中显示我的 JSX 中的图像