javascript - Javascript:Promise 实现中的错误
问题描述
我正在尝试执行异步功能,然后在Promise的帮助下控制台记录结果。恐怕我还没有完全掌握这个概念。
getlinks performs async action.
async function getLinks(param, data) {
return new Promise((resolve, reject) => {
let psub;
var name;
let g;
psub = checkForPsub(param);
var ultUrls = [];
_.each(data, o => {
title = sanitizeString(o.title);
if (psub == true) {
name = title + " u -- " + o.author;
} else {
name = title;
}
switch (o.domain) {
case "i.imgur.com":
{
// downloadImgur(o,name)
}
break;
case "imgur.com":
{
id = o.url.substring(o.url.lastIndexOf("/") + 1);
if (
o.url.includes("https://imgur.com/a/") ||
o.url.includes("https://imgur.com/gallery/") ||
o.url.includes("http://imgur.com/a/") ||
o.url.includes("http://imgur.com/gallery/")
) {
let urls = [];
let file_name;
axios
.get(
"https://api.imgur.com/3/album/" + id,
{ headers: { Authorization: "Client-ID 295ebd07bdc0ae8" } }
)
.then(res => {
let images = res.data.data.images;
_.each(images, function(v) {
var ext = v.link.split(".").pop();
if (ext == "gifv") {
ext = "mp4";
}
if (psub == true) {
file_name =
title + "--" + v.id + " " + "u--" + auth + "." + ext;
} else {
file_name = title + "--" + v.id + "." + ext;
}
let p = { url: v.link, file_name: file_name };
ultUrls.push(p);
});
})
.catch(err => {
console.log(err);
});
}
}
break;
case "i.redd.it":
{
}
break;
default:
console.log("other", o.domain);
}
}); //end each
return resolve(ultUrls);
});
}
我想等到 getlinks 完成执行任务,然后控制台记录结果。
getLinks(sub,result).then(res => console.log({res}))
但是即使在 getlink 完成之前,它也会将结果记录为空。
解决方案
最简单的答案是您承诺在异步代码 ( ) 完成之前return resolve(utlUrls)
解析 ( ) 。axios.get(...).then(...)
这是重现您的问题的最小示例:
let timeout = ms => new Promise(resolve => setTimeout(() => resolve(ms), ms));
async function getLinks(urls) {
return new Promise((resolve, reject) => {
let ultUrls = [];
urls.forEach(url =>
timeout(500).then(res => ultUrls.push(res)))
return resolve(ultUrls);
});
}
getLinks([1, 2, 3]).then(a => console.log(a));
它不起作用,因为我们在填充它之前返回了 ultUrls。我们不等待超时完成。
要解决此问题,只需使用Promise.all
. 另外删除一些不必要的承诺包装,我们得到:
let timeout = ms => new Promise(resolve => setTimeout(() => resolve(ms), ms));
function getLinks(urls) {
let ultUrls = [];
let promises = urls.map(url =>
timeout(500).then(res => ultUrls.push(res)))
return Promise.all(promises).then(a => ultUrls);
}
getLinks([1, 2, 3]).then(a => console.log(a));
此外,如果您想使用该async/await
语法,尽管在您有多个并行请求的情况下它不会给您带来太多好处,您可以将其编写为:
let timeout = ms => new Promise(resolve => setTimeout(() => resolve(ms), ms));
async function getLinks(urls) {
let ultUrls = [];
let promises = urls.map(url =>
timeout(500).then(res => ultUrls.push(res)))
await Promise.all(promises);
return ultUrls;
}
getLinks([1, 2, 3]).then(a => console.log(a));
推荐阅读
- laravel - Laravel 5.8 单元测试邮件:未发送可邮寄
- azure-devops - 跨多个项目查询 lastChanged 工作项
- python - 在 Django 模型中添加多个图像
- python - Pandas Groupby 年月成列
- automapper - AutoMapper 10.0.0 with F# - 如何在没有额外映射的情况下修复它?
- indy - Indy 10 电子邮件附件出现在正文中
- android - 颤振构建apk导致错误:找不到用于签名配置“发布”的密钥库文件
- javascript - Vue - 在这种情况下如何传递数组?
- java - Hibernate 创建两个连接同一张表
- web-scraping - 有什么方法可以得到所有标题链接的输出,因为 iv 没有也没有错误