繁体   English   中英

Promise.all fetch 在抛出错误后继续执行?

[英]Promise.all fetch continue executing after throwing error?

我正在尝试从 WordPress 开发人员参考站点获取 JSON 数据。 我需要搜索一个关键字,但不知道它是 function、class、钩子还是方法,这是我需要获取的 url 的一部分。 所以我使用 Promise.all 来循环浏览所有可能的网址。 它在response.status <= 299时有效,立即抛出错误,如果响应正常,则继续.then 很好,但是如果 JSON 存在并且只返回一个空数组,它偶尔会返回一个 ok 状态。 所以我需要检查 JSON 数据是否是一个空数组,我在第一部分似乎无法做到这一点。 据我所知,我只能检查第二部分。 如果它抛出错误,它不会继续尝试其他 url。 有什么建议么?

var keyword = 'AtomParser';
const refs = ['function', 'hook', 'class', 'method'];

// Store the promises
let promises = [];

// Cycle through each type until we find one we're looking for
for (let t = 0; t < refs.length; t++) {
  const url =
    'https://developer.wordpress.org/wp-json/wp/v2/wp-parser-' +
    refs[t] +
    '?search=' +
    keyword;
  // console.log(url);
  promises.push(fetch(url));
}
Promise.all(promises)
  .then(function(response) {
    console.log(response[0]);

    // Get the status
    console.log('Status code: ' + response[0].status);
    if (response[0].status <= 299) {
      // The API call was successful!
      return response[0].json();
    } else {
      throw new Error('Broken link status code: ' + response[0].status);
    }
  })
  .then(function(data) {
    // This is the HTML from our response as a text string
    console.log(data);

    // Make sure we have data
    if (data.length == 0) {
      throw new Error('Empty Array');
    }

    // ref
    const reference = data[0];

    // Only continue if not null or empty
    if (reference !== null && reference !== undefined && data.length > 0) {
      // Success
      // Return what I want from the reference
    }
  })
  .catch(function handleError(error) {
    console.log('Error' + error);
  });

有什么方法可以在第一部分中获取 JSON 数据,以便在检查响应状态时检查它是否在数组中?

我建议为单个请求封装成功/失败逻辑,然后您可以根据该封装的结果确定所有已解决和拒绝的响应。

例如

const checkKeyword = async (ref, keyword) => {
  const params = new URLSearchParams({ search: keyword });
  const res = await fetch(
    `https://developer.wordpress.org/wp-json/wp/v2/wp-parser-${encodeURIComponent(
      ref
    )}?${params}`
  );

  if (!res.ok) {
    throw new Error(`${res.status}: ${await res.text()}`);
  }

  const data = await res.json();

  if (data.length === 0) {
    throw new Error(`Empty results for '${ref}'`);
  }

  return { ref, data };
};

现在您可以使用Promise.any()Promise.allSettled()之类的东西分别查找第一个成功的请求或所有成功的请求

const keyword = "AtomParser";
const refs = ["function", "hook", "class", "method"];

const promises = refs.map((ref) => checkKeyword(ref, keyword));

// First success
Promise.any(promises)
  .then(({ ref, data }) => {
    console.log(ref, data);
  })
  .catch(console.error);

// All successes
Promise.allSettled(promises)
  .then((responses) =>
    responses.reduce(
      (arr, { status, value }) =>
        status === "fulfilled" ? [...arr, value] : arr,
      []
    )
  )
  .then((results) => {
    // results has all the successful responses
  });

无论出于何种原因,我都无法得到菲尔的回答,所以我最终做了以下对我来说很好的事情。 (这是针对 discord 机器人的,以防您想知道其他东西是什么)。

var keyword = 'AtomParser';
const refs = ['function', 'hook', 'class', 'method'];

// Store the successful result or error
let final: any[] = [];
let finalError = '';

// Cycle through each type until we find one we're looking for
for (let t = 0; t < refs.length; t++) {
  const url =
    'https://developer.wordpress.org/wp-json/wp/v2/wp-parser-' +
    refs[t] +
    '?search=' +
    keyword;
  console.log(url);

  // Try to fetch it
  await fetch(url)
    .then(function (response) {
      console.log(response);

      // Get the status
      console.log('Status code: ' + response.status);

      if (response.status > 299) {
        finalError = '`' + refs[t] + '` does not exist.';
        throw new Error(finalError);
      } else {
        // The API call was successful!
        return response.json();
      }
    })
    .then(function (data) {
      // This is the HTML from our response as a text string
      console.log(data);

      // Make sure we have data
      if (data.length == 0) {
        finalError = "Sorry, I couldn't find `" + keyword + '`';
        throw new Error(finalError);
      }

      // Only continue if not null or empty
      if (data[0] !== null && data[0] !== undefined && data.length > 0) {
        for (let d = 0; d < data.length; d++) {
          // Add it to the final array
          final.push(data[d]);
        }
      }
    })
    .catch(function handleError(error) {
      console.log(error);
    });
}

if (final.length > 0) {
  for (let f = 0; f < final.length; f++) {
    // ref
    const reference = final[f];

    // Get the link
    const link = reference.link;

    // Get the title
    var title = reference.title.rendered;
    title = excerpt.replace('&gt;', '>');

    // Get the excerpt
    var excerpt = reference.excerpt.rendered;
    excerpt = excerpt.replace('<p>', '');
    excerpt = excerpt.replace('</p>', '');
    excerpt = excerpt.replace('<b>', '**');
    excerpt = excerpt.replace('</b>', '**');
    console.log(excerpt);

    message.reply(
      new discord.Embed({
        title: `${title}`,
        url: link,
        description: `${excerpt}\n\n`,
        footer: {
          text: `WordPress Developer Code Reference\nhttps://developer.wordpress.org/`,
        },
      })
    );
  }
} else if (finalError != '') {
  message.reply(finalError);
} else {
  message.reply('Something went wrong...');
}

wp模块

@Phil 的回答让您走上正轨,但我想扩展他的一些想法。 URLSearchParamas的使用很棒,但您可以通过使用高级URL API 并放弃encodeURIComponent并手动构建搜索参数来改进。 请注意,我将此代码放在它自己的wp模块中,这样我就可以更轻松地分离关注点。 我们不希望所有这些代码泄漏到您的主程序中。

// wp.js

import { fetch } from "whatwg-fetch" // or your chosen implementation

const baseURL = "https://developer.wordpress.org"

async function search1(path, query) {
  const u = new URL(path, baseURL)
  u.searchParams.set("search", query)
  const result = await fetch(u)
  if (!result.ok) throw Error(`Search failed (${result.status}): ${u}`)
  return result.json()
}

search1搜索一条路径,但我们可以编写search来搜索所有必要的路径。 我认为没有任何理由对这里的每条路径都感兴趣,所以把它们写出来 -

// wp.js (continued)

function search(query) {
  const endpoints = [
    "/wp-json/wp/v2/wp-parser-function",
    "/wp-json/wp/v2/wp-parser-hook",
    "/wp-json/wp/v2/wp-parser-class",
    "/wp-json/wp/v2/wp-parser-method"
  ]
  return Promise
    .all(endpoints.map(e => search1(e, query)))
    .then(results => results.flat())
}

export { search }

主模块

请注意,我们只导出了search ,因为search1wp模块内部。 现在让我们看看如何在我们的main模块中使用它 -

// main.js

import { search } from "./wp.js"

for (const result of await search("database"))
  if(result.guid.rendered)
    console.log(`${result.title.rendered}\n${result.guid.rendered}\n`)

在这个例子中,我们首先搜索“数据库”——

wp_should_replace_insecure_home_url()
https://developer.wordpress.org/reference/functions/wp_should_replace_insecure_home_url/

wp_delete_signup_on_user_delete()
https://developer.wordpress.org/reference/functions/wp_delete_signup_on_user_delete/

get_post_datetime()
https://developer.wordpress.org/reference/functions/get_post_datetime/

wp_ajax_health_check_get_sizes()
https://developer.wordpress.org/reference/functions/wp_ajax_health_check_get_sizes/

wp_should_replace_insecure_home_url
https://developer.wordpress.org/reference/hooks/wp_should_replace_insecure_home_url/

comments_pre_query
https://developer.wordpress.org/reference/hooks/comments_pre_query/

users_pre_query
https://developer.wordpress.org/reference/hooks/users_pre_query/

WP_Object_Cache
http://developer.wordpress.org/reference/classes/wp_object_cache/

wpdb
http://developer.wordpress.org/reference/classes/wpdb/

WP_REST_Menu_Items_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_menu_items_controller/prepare_item_for_database/

WP_REST_Global_Styles_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_global_styles_controller/prepare_item_for_database/

WP_REST_Menus_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_menus_controller/prepare_item_for_database/

WP_REST_Templates_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_templates_controller/prepare_item_for_database/

WP_REST_Application_Passwords_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_application_passwords_controller/prepare_item_for_database/

wpdb::db_server_info()
https://developer.wordpress.org/reference/classes/wpdb/db_server_info/

WP_REST_Attachments_Controller::insert_attachment()
https://developer.wordpress.org/reference/classes/wp_rest_attachments_controller/insert_attachment/

WP_Debug_Data::get_database_size()
https://developer.wordpress.org/reference/classes/wp_debug_data/get_database_size/

WP_REST_Meta_Fields::update_multi_meta_value()
https://developer.wordpress.org/method/wp_rest_meta_fields/update_multi_meta_value/

另一个搜索示例

现在让我们搜索“图像”——

for (const result of await search("image"))
  if(result.guid.rendered)
    console.log(`${result.title.rendered}\n${result.guid.rendered}\n`)
get_adjacent_image_link()
https://developer.wordpress.org/reference/functions/get_adjacent_image_link/

get_next_image_link()
https://developer.wordpress.org/reference/functions/get_next_image_link/

get_previous_image_link()
https://developer.wordpress.org/reference/functions/get_previous_image_link/

wp_robots_max_image_preview_large()
https://developer.wordpress.org/reference/functions/wp_robots_max_image_preview_large/

wp_getimagesize()
https://developer.wordpress.org/reference/functions/wp_getimagesize/

is_gd_image()
https://developer.wordpress.org/reference/functions/is_gd_image/

wp_show_heic_upload_error()
https://developer.wordpress.org/reference/functions/wp_show_heic_upload_error/

wp_image_src_get_dimensions()
https://developer.wordpress.org/reference/functions/wp_image_src_get_dimensions/

wp_image_file_matches_image_meta()
https://developer.wordpress.org/reference/functions/wp_image_file_matches_image_meta/

_wp_check_existing_file_names()
https://developer.wordpress.org/reference/functions/_wp_check_existing_file_names/

edit_custom_thumbnail_sizes
https://developer.wordpress.org/reference/hooks/edit_custom_thumbnail_sizes/

get_header_image_tag_attributes
https://developer.wordpress.org/reference/hooks/get_header_image_tag_attributes/

image_editor_output_format
https://developer.wordpress.org/reference/hooks/image_editor_output_format/

wp_image_src_get_dimensions
https://developer.wordpress.org/reference/hooks/wp_image_src_get_dimensions/

wp_get_attachment_image
https://developer.wordpress.org/reference/hooks/wp_get_attachment_image/

image_sideload_extensions
https://developer.wordpress.org/reference/hooks/image_sideload_extensions/

wp_edited_image_metadata
https://developer.wordpress.org/reference/hooks/wp_edited_image_metadata/

wp_img_tag_add_loading_attr
https://developer.wordpress.org/reference/hooks/wp_img_tag_add_loading_attr/

wp_image_file_matches_image_meta
https://developer.wordpress.org/reference/hooks/wp_image_file_matches_image_meta/

get_custom_logo_image_attributes
https://developer.wordpress.org/reference/hooks/get_custom_logo_image_attributes/

Custom_Image_Header
http://developer.wordpress.org/reference/classes/custom_image_header/

WP_Image_Editor_Imagick
http://developer.wordpress.org/reference/classes/wp_image_editor_imagick/

WP_Embed
http://developer.wordpress.org/reference/classes/wp_embed/

WP_Image_Editor
http://developer.wordpress.org/reference/classes/wp_image_editor/

WP_Customize_Background_Image_Setting
http://developer.wordpress.org/reference/classes/wp_customize_background_image_setting/

WP_Customize_Header_Image_Setting
http://developer.wordpress.org/reference/classes/wp_customize_header_image_setting/

WP_Image_Editor_GD
http://developer.wordpress.org/reference/classes/wp_image_editor_gd/

WP_Customize_Header_Image_Control
http://developer.wordpress.org/reference/classes/wp_customize_header_image_control/

WP_REST_Server::add_image_to_index()
https://developer.wordpress.org/reference/classes/wp_rest_server/add_image_to_index/

WP_REST_URL_Details_Controller::get_image()
https://developer.wordpress.org/reference/classes/wp_rest_url_details_controller/get_image/

WP_Image_Editor::get_default_quality()
https://developer.wordpress.org/reference/classes/wp_image_editor/get_default_quality/

WP_Theme_JSON::get_blocks_metadata()
https://developer.wordpress.org/reference/classes/wp_theme_json/get_blocks_metadata/

WP_Image_Editor_Imagick::pdf_load_source()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/pdf_load_source/

WP_Image_Editor_Imagick::write_image()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/write_image/

WP_Image_Editor_Imagick::maybe_exif_rotate()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/maybe_exif_rotate/

WP_Image_Editor_Imagick::make_subsize()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/make_subsize/

WP_Image_Editor_GD::make_subsize()
https://developer.wordpress.org/reference/classes/wp_image_editor_gd/make_subsize/

空的搜索结果

搜索“zzz”将不会产生任何结果 -

for (const result of await search("zzz"))
  if(result.guid.rendered)
    console.log(`${result.title.rendered}\n${result.guid.rendered}\n`)
<empty result>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM