【小语法重点】result?.data?. errno === 0 前端语法“?“的含义

本文解析了JavaScript中?.?运算符在访问嵌套属性时的智能容错特性,展示了result?.data?.errno如何避免因对象不存在导致的错误,并通过实例说明其实用价值。

前端语法"?"的含义

result?.data?. errno === 0 如何理解呢?
这是js中的一种新语法。result?.data?.errno的意思是尝试获取result中的data中的error属性,它和result.data.errno的意思是一样的,但是比result.data.errno的容错性更高。

如果result对象中没有data属性,那么再获取errno时,代码容易报错,如下:

http://img.mukewang.com/climg/6036ff6b095f5a1303770112.jpg

http://img.mukewang.com/climg/6036ff7a09c7826406890115.jpg

而result?.data?.errno这种写法,代码会尝试查找errno,如果查找不到,会返回undefined,而不会报错:

http://img.mukewang.com/climg/6036ff9009146e5304290123.jpg

http://img.mukewang.com/climg/6036ff99099fb68903970096.jpg​

我进行了整合,你看对不对,并且深刻记忆这份代码 /****************************************************************************** * * Copyright (c) 2025 TP-LINK Technologies CO.,LTD. * All rights reserved. * * FILE NAME : nasw.c * VERSION : 1.0 * DESCRIPTION : 提供网络自动切换功能 * * AUTHOR : Sun Haoming (sunhaoming@tp-link.com.hk) * CREATE DATE : 10/09/2025 * * HISTORY : * 01 10/09/2025 Sun Haoming Create. * ******************************************************************************/ #include <stdio.h> #include <unistd.h> /* for chdir() */ #include <string.h> /* for strcmp() */ #include <errno.h> /* for errno */ #include <string.h> #include <linux/ethtool.h> #include <arpa/inet.h> #include <stdlib.h> #include "nasw.h" #include "dms_tool.h" #include "libdms.h" #include "libds.h" #include "packet.h" #include "nifc.h" /* 新增状态定义 */ #define PING_STATUS_UNKNOWN -1 #define PING_STATUS_FAILED 0 #define PING_STATUS_SUCCESS 1 /* 网络状态超时定义 */ #define NASW_NETWORK_CHECK_INTERVAL 10 // 网络检测间隔 #define NASW_SWITCH_DELAY 3 // 切换延迟时间 #define NASW_PHYSICAL_DEBOUNCE_DELAY 2 // 物理状态防抖延迟 #define NASW_LINK_CHANGE_DEBOUNCE 20 // 网络状态变化防抖时间(秒) /* 状态缓存结构 */ typedef struct { U8 last_phy_status; U8 last_internet_status; U8 last_auto_switch_wired; U8 last_internet_wired_enable; time_t last_change_time; S8 nasw_wired_diag; // 内部诊断结果(-1:未知 0:失败 1:成功) U8 ping_count; // 连续检测计数 int physical_debounce_timer; // 物理状态防抖定时器 time_t last_link_change; // 最后网络状态变化时间(防抖用) U8 phy_debounce_ready = 1; } NASW_STATE_CACHE; /* 全局变量 */ static NASW_STATE_CACHE g_state_cache = {0}; static int nasw_network_timer = -1; static int g_switch_delay_timer = -1; LOCAL void nasw_network_diagnose(void); LOCAL void nasw_switch_action(U8 target_mode); LOCAL void nasw_update_auto_switch(U8 phy_status, S8 wired_diag); LOCAL S8 nasw_do_ping_check(void); LOCAL void nasw_physical_debounce_handler(U32 phy_status); LOCAL void nasw_handle_physical_change(U8 new_status); /****************************************************************************** * Ping检测函数(需后续实现) ******************************************************************************/ LOCAL S8 nasw_do_ping_check(void) { // 实际实现需替换以下伪代码 /* if (ping_target("8.8.8.8") == SUCCESS) { return PING_STATUS_SUCCESS; } else { return PING_STATUS_FAILED; } */ return PING_STATUS_UNKNOWN; // 暂返回未知状态 } /****************************************************************************** * 网络诊断核心逻辑(修改版) ******************************************************************************/ LOCAL void nasw_network_diagnose(void) { LTE_CONFIG_INFO_DATA lte_config; if (0 != ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { NASW_ERROR("读取LTE配置失败"); return; } // 仅在有卡有线模式下执行诊断(这里怎么确定有卡? ) if (lte_config.internet_wired_enable == 2 // auto模式 && g_state_cache.last_phy_status == 1) { // 物理连接存在 // 执行ping检测 S8 current_result = nasw_do_ping_check(); S8 last_result=1; // 更新连续检测状态 if (last_result == current_result) { g_state_cache.ping_count++; } else { g_state_cache.ping_count = 1; last_result = current_result; } // 连续两次检测判断(关键修改点) if (g_state_cache.ping_count >= 2) { // 更新内部诊断状态 g_state_cache.nasw_wired_diag = current_result; // B→C模式转换处理(无线有卡→插线→有线有卡) if (lte_config.auto_switch_wired == 0) { lte_config.auto_wired_internet_status = (current_result == PING_STATUS_SUCCESS) ? 1 : 0; NASW_INFO("B→C模式转换更新状态: %s", (current_result == PING_STATUS_SUCCESS) ? "通" : "断"); } NASW_INFO("有线诊断结果: %s", (current_result == PING_STATUS_SUCCESS) ? "通" : "断"); } } // 触发自动切换状态更新(使用内部诊断结果) nasw_update_auto_switch( g_state_cache.last_phy_status, g_state_cache.nasw_wired_diag ); // 保存配置状态 if (0 != ds_advanced_write(LTE_INFO_DATA_PATH, &lte_config, sizeof(lte_config), DS_FLAG_NOTIFY)) { NASW_ERROR("更新LTE配置失败"); } } LOCAL void nasw_update_auto_switch(U8 phy_status, S8 wired_diag) { LTE_CONFIG_INFO_DATA lte_config; if (0 != ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { NASW_ERROR("读取LTE配置失败"); return; } U8 should_switch = 0; U8 new_switch_state = lte_config.auto_switch_wired; // 仅在有卡有线模式处理 if (lte_config.internet_wired_enable == 2) { /* 物理断开强制切4G */ if (phy_status == 0) { if (lte_config.auto_switch_wired != 0) { should_switch = 1; new_switch_state = 0; NASW_WARN("物理断开,强制切换到4G"); } } /* 物理连接时的诊断逻辑 */ else if (phy_status == 1) { // 场景1:当前4G模式且有线通畅 → 切有线 if (lte_config.auto_switch_wired == 0 && wired_diag == PING_STATUS_SUCCESS) { new_switch_state = 1; should_switch = 1; NASW_INFO("有线恢复,切换到有线"); } // 场景2:当前有线模式且诊断失败 → 切4G else if (lte_config.auto_switch_wired == 1 && wired_diag == PING_STATUS_FAILED) { new_switch_state = 0; should_switch = 1; NASW_ERROR("有线故障,切换到4G"); } } } // 立即执行切换(无延迟) if (should_switch) { nasw_switch_action(new_switch_state); } } /****************************************************************************** * 状态切换执行函数 ******************************************************************************/ LOCAL void nasw_switch_action(U8 target_mode) { LTE_CONFIG_INFO_DATA lte_config; if (0 != ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { NASW_ERROR("读取LTE配置失败"); return; } NASW_INFO("执行即时切换: %s模式", target_mode ? "有线" : "4G"); /* 切换到有线模式 */ if (target_mode == 1) { nifc_enable_wired_network(); if (g_state_cache.nasw_wired_diag == PING_STATUS_SUCCESS) { lte_disable_4g_network(); } } /* 切换到4G模式 */ else { lte_enable_4g_network(); nifc_disable_wired_network_but_keep_connection(); } // 更新状态 lte_config.auto_switch_wired = target_mode; if (0 != ds_advanced_write(LTE_INFO_DATA_PATH, &lte_config, sizeof(lte_config), DS_FLAG_NOTIFY)) { NASW_ERROR("更新切换状态失败"); } NASW_INFO("已切换到: %s模式", target_mode ? "有线" : "4G"); } /****************************************************************************** 物理状态处理函数(完整防抖版) ******************************************************************************/ LOCAL void nasw_physical_debounce_handler(U32 phy_status) { // 统一处理拔插状态 NASW_INFO("物理状态确认: %s", (phy_status == 1) ? "已插入" : "已拔出"); // 更新物理状态缓存 g_state_cache.last_phy_status = (U8)phy_status; // 有线拔出时立即重置诊断状态 if (phy_status == 0) { NASW_INFO("有线拔出,重置诊断状态"); g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN; g_state_cache.ping_count = 0; } // 触发网络诊断 nasw_network_diagnose(); // 重置定时器ID g_state_cache.physical_debounce_timer = -1; } LOCAL void nasw_handle_physical_change(U8 new_status) { // 清除现有防抖定时器 if (g_state_cache.physical_debounce_timer != -1) { inet_del_timer(g_state_cache.physical_debounce_timer); g_state_cache.physical_debounce_timer = -1; } // 创建新的防抖定时器(拔插均防抖) g_state_cache.physical_debounce_timer = inet_add_timer( (void (*)(U32))nasw_physical_debounce_handler, (U32)new_status, NASW_PHYSICAL_DEBOUNCE_DELAY, EXECUTE_SINGLE ); if (g_state_cache.physical_debounce_timer == -1) { NASW_ERROR("物理防抖定时器创建失败"); } else { NASW_INFO("物理状态变化防抖中: %s->%s (%d秒后确认)", g_state_cache.last_phy_status ? "插入" : "拔出", new_status ? "插入" : "拔出", NASW_PHYSICAL_DEBOUNCE_DELAY); } } /****************************************************************************** * 初始化与启动函数 ******************************************************************************/ LOCAL S32 nasw_init(void) { memset(&g_state_cache, 0, sizeof(NASW_STATE_CACHE)); g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN; g_state_cache.physical_debounce_timer = -1; g_state_cache.last_link_change = time(NULL); return OK; } LOCAL S32 nasw_start(void) { PHY_STATUS phy_status; LINK_STATUS link_status; LTE_CONFIG_INFO_DATA lte_config; NASW_INFO("启动NASW模块..."); // 读取物理状态 if (0 == ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS))) { NASW_ERROR("读取PHY状态失败"); return ERROR; } // 读取网络状态 if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { NASW_ERROR("读取LINK状态失败"); return ERROR; } // 初始化LTE配置 if (0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { NASW_ERROR("读取LTE配置失败,使用默认值"); memset(&lte_config, 0, sizeof(lte_config)); } // 设置初始状态缓存 g_state_cache.last_phy_status = phy_status.ether; g_state_cache.last_internet_status = link_status.internet_status; g_state_cache.last_auto_switch_wired = lte_config.auto_switch_wired; g_state_cache.last_internet_wired_enable = lte_config.internet_wired_enable g_state_cache.last_change_time = time(NULL); if (lte_config.internet_wired_enable != 2) { NASW_ERROR("non-auto mode, self-selected internet mode, WIRED=%d)", lte_config.internet_wired_enable); lte_config.auto_switch_wired = 2; ds_write(LTE_INFO_DATA_PATH, &lte_config, sizeof(lte_config)); } /* 仅当 internet_wired_enable == 2 时才处理 auto_switch_wired */ if (lte_config.internet_wired_enable == 2) { if (phy_status.ether == 1) { lte_config.auto_switch_wired = 1; } else { lte_config.auto_switch_wired = 0; } if (0 != ds_advanced_write(LTE_INFO_DATA_PATH, &lte_config, sizeof(lte_config), DS_FLAG_NOTIFY)) { NASW_ERROR("写入初始LTE配置失败"); } } NASW_INFO("执行首次网络诊断..."); nasw_network_diagnose(); // 同步执行 // 启动网络诊断定时器 nasw_network_timer = inet_add_timer( (void (*)(U32))nasw_network_diagnose, // 回调函数 0, // 参数 NASW_NETWORK_CHECK_INTERVAL, // 间隔时间 EXECUTE_FOREVER // 永久执行 ); if (nasw_network_timer == -1) { NASW_ERROR("创建网络诊断定时器失败"); } if (lte_config.internet_wired_enable == 1) { NASW_INFO("NASW未处于auto模式,初始模式: %s", lte_config.internet_wired_enable ? "有线" : "4G"); } else if (lte_config.internet_wired_enable == 2) { NASW_INFO("NASW启动完成,初始模式: %s", lte_config.auto_switch_wired ? "有线" : "4G"); } return OK; } /****************************************************************************** * reload函数(含防抖和B→C处理) ******************************************************************************/ LOCAL S32 nasw_reload(DS_MSG *msg) { if (!msg) return OK; PHY_STATUS phy_status = {0}; LINK_STATUS link_status = {0}; LTE_CONFIG_INFO_DATA lte_config = {0}; BOOL phy_changed = 0; BOOL link_changed = 0; BOOL lte_changed = 0; // 检查 PHY_STATUS_PATH 变化 if (ds_path_id_exist(msg->id, msg->num, PHY_STATUS_PATH)) { if (0 == ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS))) { NASW_ERROR("读取PHY状态失败"); return ERROR; } if (g_state_cache.last_phy_status != phy_status.ether) { phy_changed = 1; g_state_cache.last_phy_status = phy_status.ether; } } // 检查 LINK_STATUS_PATH 变化 if (ds_path_id_exist(msg->id, msg->num, LINK_STATUS_PATH)) { if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { NASW_ERROR("读取LINK状态失败"); return ERROR; } if (g_state_cache.last_internet_status != link_status.internet_status) { link_changed = 1; g_state_cache.last_internet_status = link_status.internet_status; } } // 检查 LTE_INFO_DATA_PATH 变化 if (ds_path_id_exist(msg->id, msg->num, LTE_INFO_DATA_PATH)) { if (0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { NASW_ERROR("读取LTE配置失败"); return ERROR; } // 处理非自动模式 if (lte_config.internet_wired_enable != 2) { NASW_INFO("非自动模式(WIRED=%d)", lte_config.internet_wired_enable); lte_config.auto_switch_wired = 2; if (0 != ds_write(LTE_INFO_DATA_PATH, &lte_config, sizeof(lte_config))) { NASW_ERROR("web切换至非auto模式"); } } // 处理自动模式状态变化 if (lte_config.internet_wired_enable == 2) { if (g_state_cache.last_auto_switch_wired != lte_config.auto_switch_wired) { lte_changed = 1; g_state_cache.last_auto_switch_wired = lte_config.auto_switch_wired; } } } // B→C模式特殊处理(无线有卡→插线→有线有卡) if (phy_changed && phy_status.ether == 1 && lte_config.internet_wired_enable == 2 && lte_config.auto_switch_wired == 0) { NASW_INFO("B→C模式转换(插线),重置诊断状态"); g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN; g_state_cache.ping_count = 0; nasw_network_diagnose(); // 立即触发 } // C状态处理:有线物理连接+Ping检测 if (lte_config.internet_wired_enable == 2 && phy_status.ether == 1 && lte_config.auto_switch_wired == 1) { nasw_network_diagnose(); // 持续监控 } // 网络状态变化处理(带防抖) if (link_changed) { time_t now = time(NULL); // 防抖处理:20秒内不重复触发 if (now - g_state_cache.last_link_change > NASW_LINK_CHANGE_DEBOUNCE) { NASW_INFO("检测到网络状态变化:%d -> %d(防抖通过)", g_state_cache.last_internet_status, link_status.internet_status); // 更新最后变化时间 g_state_cache.last_link_change = now; // 物理连接存在时触发诊断 if (g_state_cache.last_phy_status == 1) { nasw_network_diagnose(); } } else { NASW_ERROR("网络状态变化%ds内被过滤(防抖)", (int)(now - g_state_cache.last_link_change)); } } // 处理物理连接状态变化(有线插入/拔出) if (phy_changed) { NASW_INFO("物理连接状态变化:%d -> %d", g_state_cache.last_phy_status, phy_status.ether); // 触发物理状态变化处理(带防抖机制) nasw_handle_physical_change(phy_status.ether); // 有线拔出时立即重置诊断状态 if (phy_status.ether == 0) { NASW_INFO("检测到有线拔出,重置诊断状态"); g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN; g_state_cache.ping_count = 0; } } // 处理切换模式变化 if (lte_changed) { NASW_INFO("切换模式变更:%d -> %d", g_state_cache.last_auto_switch_wired, lte_config.auto_switch_wired); // 立即触发诊断(确保状态同步) nasw_network_diagnose(); } return OK; } /****************************************************************************** * 停止函数(完整清理资源) ******************************************************************************/ LOCAL S32 nasw_stop(void) { NASW_INFO("正在停止NASW模块..."); // 1. 清理网络诊断定时器 if (nasw_network_timer != -1) { inet_del_timer(nasw_network_timer); nasw_network_timer = -1; NASW_INFO("网络诊断定时器已清理"); } // 2. 清理切换延迟定时器 if (g_switch_delay_timer != -1) { inet_del_timer(g_switch_delay_timer); g_switch_delay_timer = -1; NASW_INFO("切换延迟定时器已清理"); } // 3. 清理物理防抖定时器 if (g_state_cache.physical_debounce_timer != -1) { inet_del_timer(g_state_cache.physical_debounce_timer); g_state_cache.physical_debounce_timer = -1; NASW_INFO("物理防抖定时器已清理"); } // 4. 重置状态缓存(包括诊断状态) memset(&g_state_cache, 0, sizeof(NASW_STATE_CACHE)); g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN; NASW_INFO("NASW模块已完全停止"); return OK; } LOCAL void nasw_main() { DS_DAT_MON_DESC nasw_data_monitor[] = { DS_DAT_MON(LINK_STATUS_PATH, DATA_ATTRI_NOTIFY), DS_DAT_MON(PHY_STATUS_PATH, DATA_ATTRI_NOTIFY), #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT DS_DAT_MON(LTE_INFO_DATA_PATH, DATA_ATTRI_NOTIFY), #endif }; DS_MOD_DESC nasw_module = DS_STRUCT_MOD("nasw", nasw_init, NULL, nasw_reload, nasw_start, nasw_stop, NULL, nasw_data_monitor); MODULE *module_node = ds_register_module("nasw", &nasw_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(nasw_main);
最新发布
10-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值