【问题标题】:Javascript: Error in Promise implementationJavascript:Promise 实现中的错误
【发布时间】:2019-06-25 23:46:59
【问题描述】:

我正在尝试执行异步功能,然后在 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 完成之前将结果记录为空。

【问题讨论】:

  • 查看承诺文档here。当异步操作完成时,您应该调用 resolve。这应该在 axios 的 .then 中。你不应该返回解析的结果,你只需调用它。文档中的例子很清楚,只要在此基础上实现你的代码即可。
  • 此外,如果您将执行多个异步任务,一种常见的技术是将每个异步任务返回的 Promise 推送到一个数组中,并在其上使用 Promise.all()Promise.allSettled() 方法在采取行动之前,promise 数组等​​待它们全部完成(或者在 Promise.all 的情况下,要么全部完成,要么第一个拒绝)。所有在 Chris 链接的文档中都有描述。
  • 我一定会检查码头的。您建议将解决方案放入 axios 中,但我正在多次执行 axios 调用。
  • @thmsdnnr 知道了。我试试看

标签: javascript asynchronous promise


【解决方案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));

它不起作用,因为我们在填充它之前返回了 ultUrls。我们不会等待超时完成。

要解决此问题,只需使用 Promise.all 等待 Promise 完成。另外删除一些不必要的承诺包装,我们得到:

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));

【讨论】:

    【解决方案2】:

    我会这样做。将 Promise 推送到 Promise 数组中。然后调用 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;
      });
    

    }

    【讨论】:

    • 抱歉,我删除了你不需要的 resolve() 部分。直接退货吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多