2025-04-03【JavaScript】经典场景函数

1 创造一个阻塞线程的延迟函数

10毫秒延迟

await new Promise((resolve) => setTimeout(resolve, 10));

2 Promise.race的用法

Promise.race 是 JavaScript 中 Promise 对象的一个静态方法,它接收一个可迭代对象(通常是数组)作为参数,这个可迭代对象包含多个 Promise 实例。Promise.race 方法会返回一个新的 Promise,这个新 Promise 会在传入的 Promise 数组中任意一个 Promise 完成(无论是成功还是失败)时,立即以相同的结果状态完成。

语法

Promise.race(iterable);
  • iterable:一个可迭代对象,如数组,其中的每个元素都是一个 Promise 实例。

返回值

返回一个新的 Promise 实例,它会根据传入的 Promise 数组中最先完成的 Promise 的结果来确定自身的状态和结果。如果最先完成的 Promise 成功(resolved),那么返回的新 Promise 也会以相同的值成功;如果最先完成的 Promise 失败(rejected),那么返回的新 Promise 也会以相同的错误原因失败。

示例代码

以下是一些使用 Promise.race 的示例,帮助你更好地理解它的用法。

示例 1:多个 Promise 竞争,先完成的决定结果

const promise1 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('Promise 1 完成');
    }, 2000);
});

const promise2 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('Promise 2 完成');
    }, 1000);
});

Promise.race([promise1, promise2])
   .then((result) => {
        console.log(result); // 输出: Promise 2 完成
    })
   .catch((error) => {
        console.error(error);
    });

在这个例子中,promise2promise1 先完成,所以 Promise.race 返回的 Promise 会以 promise2 的结果 'Promise 2 完成' 成功。

示例 2:包含失败的 Promise

const promise3 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('Promise 3 完成');
    }, 2000);
});

const promise4 = new Promise((_, reject) => {
    setTimeout(() => {
        reject(new Error('Promise 4 失败'));
    }, 1000);
});

Promise.race([promise3, promise4])
   .then((result) => {
        console.log(result);
    })
   .catch((error) => {
        console.error(error.message); // 输出: Promise 4 失败
    });

这里 promise4 先完成,但它是失败的,所以 Promise.race 返回的 Promise 会以 promise4 的错误原因 'Promise 4 失败' 失败。

实际应用场景

  • 超时处理:在前面你提到的代码中,就使用 Promise.race 实现了超时处理。将一个异步操作和一个定时器 Promise 放在一起竞争,如果定时器先完成,就认为异步操作超时了。
  • 多个数据源获取数据:当有多个数据源可以获取相同的数据时,可以同时发起多个请求,使用 Promise.race 来获取最先返回的数据,提高响应速度。

给dealer添加超时返回机制

let reply;
let timer;
try {
    // 使用Promise.race来进行超时控制和router的通信 有回复立即返回,超时则抛出超时错误
    reply = await Promise.race([
        dealer.receive(),
        new Promise((resolve, reject) => {
            timer = setTimeout(() => {
                reject(new Error('Reply Timeout'));
            }, timeout);
        })
    ]);
} catch (error) {
    if (error.message === 'Reply Timeout') {
        clearTimeout(timer);     // 清除定时器
        dealer.close();
        console.error(`${dealerID} 超时关闭`);
        return 'Reply Timeout';  // 返回超时结果 停止循环
    }
    throw error;                 // 抛出非超时错误
}

3 Promise函数的三种返回值状态

  • pending(进行中)
    这是 Promise 对象的初始状态。当你创建一个 Promise 实例时,它一开始就处于 pending 状态。在此状态下,Promise 的操作还在进行,结果尚未确定
const myPromise = new Promise((resolve, reject) => {
    // 模拟一个耗时操作
    setTimeout(() => {
        // 这里在 3 秒后才会有结果,所以在这 3 秒内,Promise 处于 pending 状态
    }, 3000);
});
console.log(myPromise); 

不显示调用resolvereject就会一直处于pending状态

  • fulfilled(已成功)
    当 Promise 内部的操作成功完成时,它会从 pending 状态转变为 fulfilled 状态。此时可以通过调用 resolve 函数来传递操作的结果
const myPromise = new Promise((resolve, reject) => {
    // 模拟一个成功的操作
    setTimeout(() => {
        resolve('操作成功');
    }, 2000);
});

myPromise.then((result) => {
    console.log(result); 
});

setTimeout 完成后,resolve 函数被调用,Promise 状态变为fulfilledthen方法中的回调函数会接收resolve传递的值 '操作成功' 并执行。

  • rejected(已失败)
    当 Promise 内部的操作出现错误或未能成功完成时,它会从 pending 状态转变为 rejected 状态。此时可以通过调用 reject 函数来传递错误信息
const myPromise = new Promise((resolve, reject) => {
    // 模拟一个失败的操作
    setTimeout(() => {
        reject(new Error('操作失败'));
    }, 2000);
});

myPromise.catch((error) => {
    console.error(error.message); 
});

setTimeout完成后,reject 函数被调用,Promise 状态变为 rejectedcatch方法中的回调函数会接收 reject 传递的错误对象并执行
还可以用then函数同时处理fulfilledreject

myPromise.then(
    (result) => {
        console.log('成功结果:', result);
    },
    (error) => {
        console.error('使用 then 捕获的错误:', error.message);
    }
);

因为promise的返回结果是reject,所以第一个回调函数不会执行
标准做法: 分别使用thencatch处理成功和失败

myPromise
  .then((result) => {
        console.log(result);
    })
  .catch((error) => {
        console.error(error.message); // 输出: 操作失败
    });

4 快速将对象包装为JSON和解JSON字符串

  • 包装成字符串
const sendConfig = () => {
  const config = {
    userInput: userInput.value
  };
  const jsonConfig = JSON.stringify(config);
  ipcRenderer.send('config', jsonConfig);
};
  • 再解析为对象
ipcMain.on('config', (event, jsonConfig) => {
  try {
    const config = JSON.parse(jsonConfig);
    console.log('接收到的配置:', config);
  } catch (error) {
    console.error('解析JSON时出错:', error);
  }
});

5 快速按数字升/降序排列

升序

 props.chatList.sort((a, b) => a.order - b.order)  // 为负数,a在前,小的在前

降序

props.chatList.sort((a, b) => b.order - a.order)  // 大的在前

更改会覆盖原数组

6 异步函数的默认返回promise.resolve机制

const myPromise = async () => {
        return '你好'
    }

return就自动返回promise.resolve,不写隐式返回,只是promise.resolve = undefined
达到fulfilled状态

7 打印对象内属性个数

console.log(Object.keys(groupContactList.value).length)

8 6个默认假值

JavaScript 里有 6 个值在转换为布尔值时会被当作假值,它们分别是:

  • false
  • 0
  • ''(空字符串 双单引号)
  • null
  • undefined
  • NaN

注意空对象{} 空数组[]的布尔值是true

9 等待图片加载完成的回调函数

const preloadImage = (url, callback) => {
    const img = new Image()
    img.src = url
    img.onload = () => {
        callback(url) // 图片加载完成后执行回调
    }
}

使用示例,等待图片加载完成设置为背景图片

preloadImage(selectedPostUrl, (loadedUrl) => {
    requestAnimationFrame(() => {
        setTimeout(() => {
        console.log('backgroundImageUrl.value:', backgroundImageUrl.value)
            backgroundImageUrl.value = loadedUrl  // 延迟一段时间后再更新背景
        }, 0)
        backgroundImageUrl.value = loadedUrl  // 记录当前加载图
    })
})

10 多种快速查找数组中满足条件元素的方法

  1. Array.prototype.find() - 返回第一个满足条件的元素
const foundItem = chatList.value.find(chat => chat.user_id === selectedChat.value.user_id);
// foundItem 是找到的元素或undefined
  1. Array.prototype.some() - 检查是否存在满足条件的元素(返回布尔值)
const exists = chatList.value.some(chat => chat.user_id === selectedChat.value.user_id);
// exists 是 true/false
  1. Array.prototype.findIndex() - 返回第一个满足条件的元素索引
const index = chatList.value.findIndex(chat => chat.user_id === selectedChat.value.user_id);
// index 是索引号或-1

11 在组件中创建与销毁监听

处理函数

// 事件message:isSendSuccess的处理函数
const handleSendSuccess = (event, isSendSuccess) => {
  if (isSendSuccess) {
    inputTextObj = {...inputTextObj, ...{sendStatus: ' ', isStop: true}}
    console.log('用户输入内容已成功发送至服务器')
    emit('inputTextEvent', inputTextObj)
  }

// 在组件创建时注册监听
onMounted(() => {
  window.ipcRenderer.on(chatEvents.IS_SEND_SUCCESS, handleSendSuccess)
})
// 在组件销毁时移除监听
onBeforeUnmount(() => {
  window.ipcRenderer.removeListener(chatEvents.IS_SEND_SUCCESS, handleSendSuccess)
})

12 把Date用对象形式打印出来

const dateStr = "2025-05-03 10:36:42";
const dateObj = new Date(dateStr);
console.dir(dateObj);

提取年月日 时分秒

const dateStr = "2025-05-03 10:36:42";
const dateObj = new Date(dateStr);

// 提取年月日
const year = dateObj.getFullYear();    // 2025
const month = dateObj.getMonth() + 1;  // 5 (注意:月份从0开始,需+1)
const day = dateObj.getDate();         // 3

// 提取时分秒
const hours = dateObj.getHours();      // 10
const minutes = dateObj.getMinutes();  // 36
const seconds = dateObj.getSeconds();  // 42

console.log(`${year}-${month}-${day} ${hours}:${minutes}:${seconds}`);
// 输出: "2025-5-3 10:36:42"

按时时间排序:新——>旧

// 假设你的数组结构如下
const data = [
  {id: 1, time: "2025-05-03 10:36:42"},
  {id: 2, time: "2023-02-15 08:20:00"},
  {id: 3, time: "2024-11-28 16:45:30"}
];

// 按时间降序排序(新在前,旧在后)
data.sort((a, b) => {
  // 将时间字符串转换为Date对象的时间戳进行比较
  return new Date(b.time).getTime() - new Date(a.time).getTime();
});

console.log(data);

13 async

只要一个函数用了async,它的返回值一定是Promise
接收方可以获取传出的Promise或者使用await解包出内部resolved值,也就是代码上写的
return XXX或者resolved(XXX)

14 JS的push_front

于在数组开头添加一个或多个元素:

let arr = [2, 3];
arr.unshift(1); // 在数组前端插入
console.log(arr); // 输出: [1, 2, 3]

使用ES6展开运算符
let arr = [2, 3];
arr = [1, ...arr]; // 创建新数组
console.log(arr); // 输出: [1, 2, 3]

使用 concat() 方法
let arr = [2, 3];
arr = [1].concat(arr);
console.log(arr); // 输出: [1, 2, 3]


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容