Javascript:Promise实现中的错误

时间:2019-06-25 15:14:20

标签: javascript asynchronous 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完成之前,它也会将结果记录为空。

2 个答案:

答案 0 :(得分:1)

这就是我要做的。将诺言推送到诺言数组。然后调用Promise.resolve,将最终解决所有问题。

  async function getLinks(param, data) {
let psub;
var name;
let g;
let promises = [];
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;
        // I would break this out into it's own function probabaly
        promises.push(
        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 Promise.all(promises)
  .then((yourData) => {
    return yourData;
  });

}

答案 1 :(得分:1)

最简单的答案是,您保证在完成异步代码(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));

这是行不通的,因为在填充之前我们会返回ultUrl。我们不等待超时完成。

要解决此问题,只需等待使用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));