DrillLab
练习Practice

动手做Get your hands on it

练习跟着课文走 —— 每节课尾都有本课的练习。这一页是全部练习的总库,想集中刷题的时候来。 每个练习都写清了它来自哪一节,卡住了就回去看那一节。Practice follows the lessons — every lesson ends with the exercises for that lesson. This page is the whole library, for when you want to drill in one sitting. Each exercise names the lesson it came from, so you can go back when you stall.

0 / 148个做对过you got right

练习Exercises

筛出 26 个练习(共 148 个) · 第 2 / 3 页。Showing 26 of 148 · page 2 / 3.
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L2Debug LabDebug Lab故障 1 · 路径大小写Fault 1 · upper and lower case in a path

新建了组件之后启动开发服务器,Vite 直接报错,页面白屏。

You add a new component, start the dev server, and Vite reports an error right away. The page is blank.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
[plugin:vite:import-analysis] Failed to resolve import "./components/notemanager" from "src/App.tsx". Does the file exist? /Users/me/react-notes-app/src/App.tsx:1:24 1 | import NoteManager from "./components/notemanager"; | ^
TSXsrc/App.tsx示意Illustrative
1import NoteManager from "./components/notemanager";
2
3function App() {
4 return <NoteManager />;
5}
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L2Debug LabDebug Lab故障 2 · props 名字对不上Fault 2 · the prop names do not match

重构时把父组件传的 prop 名改了,子组件忘了跟着改。 页面能显示,但点 Delete 直接崩。

During a refactor the prop name passed by the parent was changed, and the child component was not changed to match. The page still renders, but clicking Delete crashes it.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
Uncaught TypeError: onDelete is not a function at onClick (NoteItem/index.tsx:18:29) at HTMLUnknownElement.callCallback # 另外 TypeScript 那边也在报: src/components/NoteTable/index.tsx(20,7): error TS2322: Type '{ key: number; note: Note; onRemove: (id: number) => void; onEdit: ... }' is not assignable to type 'IntrinsicAttributes & NoteItemProps'. Property 'onDelete' is missing in type ... but required in type 'NoteItemProps'.Uncaught TypeError: onDelete is not a function at onClick (NoteItem/index.tsx:18:29) at HTMLUnknownElement.callCallback # TypeScript is reporting something too: src/components/NoteTable/index.tsx(20,7): error TS2322: Type '{ key: number; note: Note; onRemove: (id: number) => void; onEdit: ... }' is not assignable to type 'IntrinsicAttributes & NoteItemProps'. Property 'onDelete' is missing in type ... but required in type 'NoteItemProps'.
TSX两处不一致The two places that disagree示意Illustrative
1// NoteTable 里传下去的名字:
2<NoteItem
3 key={note.id}
4 note={note}
5 onRemove={onDelete} // ← 传的是 onRemove
6 onEdit={onEdit}
7/>
8
9// NoteItem 的 props 接口和解构:
10export interface NoteItemProps {
11 note: Note;
12 onDelete: (id: number) => void; // ← 期望的是 onDelete
13 onEdit: (note: Note) => void;
14}
15const NoteItem: React.FC<NoteItemProps> = ({ note, onDelete, onEdit }) => {
1// The name NoteTable passes down:
2<NoteItem
3 key={note.id}
4 note={note}
5 onRemove={onDelete} // ← it passes onRemove
6 onEdit={onEdit}
7/>
8
9// The props interface of NoteItem, and how it destructures them:
10export interface NoteItemProps {
11 note: Note;
12 onDelete: (id: number) => void; // ← it expects onDelete
13 onEdit: (note: Note) => void;
14}
15const NoteItem: React.FC<NoteItemProps> = ({ note, onDelete, onEdit }) => {
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L2Debug LabDebug Lab故障 3 · 测试找不到元素Fault 3 · the test cannot find the element

代码看起来完全正确,手动点也没问题,但两个测试挂了。

The code looks entirely correct and clicking through it by hand works, but two tests fail.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
FAIL src/NoteManager.test.tsx > adds a note TestingLibraryElementError: Unable to find an element by: [data-testid="form-input"] Ignored nodes: comments, script, style <body> <div> <div class="layout-column ..." data-testid="note-manager"> <div class="card ..."> <form data-testid="note-form"> <section class="layout-row ..."> <label class="form-title-label">Title:</label> <input type="text" placeholder="Title" data-testid="title-input" ... /> ...
TSXsrc/components/NoteForm/index.tsx示意Illustrative
1<input
2 type="text"
3 placeholder="Title"
4 value={title}
5 onChange={(e) => setTitle(e.target.value)}
6 data-testid="title-input"
7 className="form-input"
8/>
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L3Debug LabDebug Lab故障 4 · 编辑后列表毫无变化(综合题)Fault 4 · the list does not change after an edit (mixed question)

这一题不告诉你是哪一类。控制台干净,console.log 显示数据是对的。 自己分诊。

This one does not tell you which category it is. The console is clean, and console.log shows the data is correct. Sort it yourself.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
# 没有任何报错。 # 复现:添加 "A"、"B" 两条 → 点 B 的 Edit → 改成 "B2" → 点 Update # 期望:列表变成 A、B2 # 实际:列表还是 A、B # 在 handleSubmitNote 里插了日志: console.log("submitted:", submittedNote); // → submitted: { id: 1785737900978, title: 'B2', content: '...' } ← 数据是对的 console.log("after:", notes); // → after: [ {title:'A'...}, {title:'B2'...} ] ← 数组里也是对的! # 但屏幕上还是 B。 # 测试结果: # ✕ edits a note in place# No error at all. # Repro: add "A" and "B" → click Edit on B → change it to "B2" → click Update # Expected: the list becomes A, B2 # Actual: the list is still A, B # Logs added inside handleSubmitNote: console.log("submitted:", submittedNote); // → submitted: { id: 1785737900978, title: 'B2', content: '...' } ← the data is right console.log("after:", notes); // → after: [ {title:'A'...}, {title:'B2'...} ] ← the array is right too! # But the screen still shows B. # Test result: # ✕ edits a note in place
TSX有问题的 handleSubmitNoteThe handleSubmitNote with the problem示意Illustrative
1const handleSubmitNote = (submittedNote: Note) => {
2 if (noteToEdit) {
3 const i = notes.findIndex((n) => n.id === submittedNote.id);
4 notes[i] = submittedNote;
5 setNotes(notes);
6 setNoteToEdit(null);
7 } else {
8 setNotes((prev) => [...prev, submittedNote]);
9 }
10};
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From N+1 问题与 DataLoaderThe N+1 problem and DataLoader · Federation 考试Federation exam
L2Debug LabDebug LabDebug Lab · DataLoader 报 is not a functionDebug Lab · DataLoader reports is not a function

npm test,其中一个 DataLoader 相关的测试挂了。 报错指向 loader 内部。

You run npm test and one of the DataLoader tests fails. The error points inside the loader.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
● Order Resolvers › DataLoader functionality › should batch multiple order requests TypeError: orderDataSource.getOrderById is not a function 29 | 30 | const orders = await Promise.all( > 31 | orderIds.map(id => orderDataSource.getOrderById(id)) | ^ 32 | ); 33 | 34 | return orders; at src/resolvers/orderResolvers.js:31:42 at Array.map (<anonymous>) at DataLoader._batchLoadFn (src/resolvers/orderResolvers.js:31:16)
JavaScriptsrc/resolvers/orderResolvers.js示意Illustrative
1function createOrderLoader(orderDataSource) {
2 return new DataLoader(async orderIds => {
3 const orders = await Promise.all(
4 orderIds.map(id => orderDataSource.getOrderById(id))
5 );
6 return orders;
7 });
8}
9
10// 参考:OrderDataSource 上真实存在的方法
11// class OrderDataSource {
12// async getOrder(id) { ... }
13// async getOrdersByUserId(userId) { ... }
14// async createOrder(userId, items) { ... }
15// }
1function createOrderLoader(orderDataSource) {
2 return new DataLoader(async orderIds => {
3 const orders = await Promise.all(
4 orderIds.map(id => orderDataSource.getOrderById(id))
5 );
6 return orders;
7 });
8}
9
10// For reference: the methods OrderDataSource really has
11// class OrderDataSource {
12// async getOrder(id) { ... }
13// async getOrdersByUserId(userId) { ... }
14// async createOrder(userId, items) { ... }
15// }
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From 三处埋雷:怎么系统地找出来The three planted bugs: how to find them systematically · Federation 考试Federation exam
L3Debug LabDebug LabDebug Lab · Cannot read properties of undefinedDebug Lab · Cannot read properties of undefined

Mutation.createOrder 的测试挂了。 报错说在读一个 undefined 的属性。自己分诊。

The Mutation.createOrder test fails. The error says something read a property of undefined. Diagnose it yourself.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
● Order Resolvers › Mutation.createOrder resolver › should create a new order successfully GraphQLError: Failed to create order 91 | } catch (error) { 92 | console.error(`[${correlationId}] Error creating order:`, error.message); > 93 | throw new GraphQLError('Failed to create order', { # 往上翻,console.error 打出的原始错误是: console.error [test-correlation-id] Error creating order: Cannot read properties of undefined (reading 'createOrder')● Order Resolvers › Mutation.createOrder resolver › should create a new order successfully GraphQLError: Failed to create order 91 | } catch (error) { 92 | console.error(`[${correlationId}] Error creating order:`, error.message); > 93 | throw new GraphQLError('Failed to create order', { # Scroll up: the raw error that console.error printed is console.error [test-correlation-id] Error creating order: Cannot read properties of undefined (reading 'createOrder')
JavaScriptsrc/resolvers/orderResolvers.js示意Illustrative
1const order = await dataSources.orderAPI.createOrder({ userId, items });
2
3// 参考:index.js 里 context 的 return
4// return {
5// dataSources: { orderDataSource, inventoryDataSource, shippingDataSource },
6// loaders: { shippingInfoLoader, orderLoader },
7// correlationId
8// };
1const order = await dataSources.orderAPI.createOrder({ userId, items });
2
3// For reference: what the context function in index.js returns
4// return {
5// dataSources: { orderDataSource, inventoryDataSource, shippingDataSource },
6// loaders: { shippingInfoLoader, orderLoader },
7// correlationId
8// };
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From 三处埋雷:怎么系统地找出来The three planted bugs: how to find them systematically · Federation 考试Federation exam
L3Debug LabDebug LabDebug Lab · 错误码不对(不报错的那种 bug)Debug Lab · The wrong error code (the kind of bug that throws nothing)

代码跑得通,没有异常。但测试说错误码不对。 这是三处埋雷里最值得理解的一处。

The code runs and raises no exception, but the test says the error code is wrong. Of the three planted bugs, this is the one most worth understanding.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
● Order Resolvers › Error handling › should return structured error for validation failures expect(received).toBe(expected) // Object.is equality Expected: "INVALID_INPUT" Received: "SERVICE_ERROR" # 测试代码: # const input = { userId: '789', items: [] }; ← 空 items,应该被校验拦下 # try { # await resolvers.Mutation.createOrder({}, input, context); # throw new Error('Should have thrown an error'); # } catch (error) { # expect(error.extensions.code).toBe('INVALID_INPUT'); # }● Order Resolvers › Error handling › should return structured error for validation failures expect(received).toBe(expected) // Object.is equality Expected: "INVALID_INPUT" Received: "SERVICE_ERROR" # The test code: # const input = { userId: '789', items: [] }; ← empty items, validation should stop it # try { # await resolvers.Mutation.createOrder({}, input, context); # throw new Error('Should have thrown an error'); # } catch (error) { # expect(error.extensions.code).toBe('INVALID_INPUT'); # }
JavaScriptsrc/resolvers/orderResolvers.js示意Illustrative
1try {
2 if (!userId || !items || items.length === 0) {
3 throw new GraphQLError('Invalid order input', {
4 extensions: { code: ErrorCodes.INVALID_INPUT, correlationId }
5 });
6 }
7 const order = await dataSources.orderDataSource.createOrder(userId, pricedItems);
8 return order;
9} catch (error) {
10 console.error(`[${correlationId}] Error creating order:`, error.message);
11 throw new GraphQLError('Failed to create order', {
12 extensions: { code: ErrorCodes.SERVICE_ERROR, correlationId }
13 });
14}
1try {
2 if (!userId || !items || items.length === 0) {
3 throw new GraphQLError('Invalid order input', {
4 extensions: { code: ErrorCodes.INVALID_INPUT, correlationId }
5 });
6 }
7 const order = await dataSources.orderDataSource.createOrder(userId, pricedItems);
8 return order;
9} catch (error) {
10 console.error(`[${correlationId}] Error creating order:`, error.message);
11 throw new GraphQLError('Failed to create order', {
12 extensions: { code: ErrorCodes.SERVICE_ERROR, correlationId }
13 });
14}
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From 六个端点:状态码就是这道题的全部Six endpoints: the status codes are the whole task · Federation 考试Federation exam
L3Debug LabDebug LabDebug Lab · 查一个不存在的订单,返回了 200Debug Lab · Asking for an order that does not exist returns 200

五个测试全过。但手动 curl 一个不存在的 id, 得到 200 和一个空 body。期望是 404 加一段 JSON。

All five tests pass. But curl an id that does not exist by hand and you get a 200 with an empty body. It should be a 404 with a piece of JSON.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
$ curl -i -s localhost:8080/api/orders/999 HTTP/1.1 200 Content-Length: 0 # 期望: # HTTP/1.1 404 # { "timestamp": "...", "status": 404, "message": "Order not found with id: 999" } # mvn test:Tests run: 5, Failures: 0 ← 测试全过!$ curl -i -s localhost:8080/api/orders/999 HTTP/1.1 200 Content-Length: 0 # Expected: # HTTP/1.1 404 # { "timestamp": "...", "status": 404, "message": "Order not found with id: 999" } # mvn test: Tests run: 5, Failures: 0 ← every test passes!
Java有问题的实现The broken implementation示意Illustrative
1@GetMapping("/api/orders/{id}")
2public ResponseEntity<Order> getOrderById(@PathVariable Long id) {
3 logger.info("GET /api/orders/{} correlationId={}", id, correlationId());
4 try {
5 return ResponseEntity.ok(orderService.getOrderById(id));
6 } catch (EntityNotFoundException ex) {
7 return null;
8 }
9}
1@GetMapping("/api/orders/{id}")
2public ResponseEntity<Order> getOrderById(@PathVariable Long id) {
3 logger.info("GET /api/orders/{} correlationId={}", id, correlationId());
4 try {
5 return ResponseEntity.ok(orderService.getOrderById(id));
6 } catch (EntityNotFoundException ex) {
7 return null;
8 }
9}
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · Federation 十种典型故障Debug Lab · ten common Federation failures · Federation 考试Federation exam
L3Debug LabDebug Lab故障 1 · resolver 写了,字段还是 nullFault 1 · the resolver is written, the field is still null

你确信写了 shippingInfo 的实现, 测试也不报错,但查询返回的 shippingInfonull。控制台里连你加的 log 都没打印。

You are sure you wrote an implementation for shippingInfo, and no test reports anything, but the query returns shippingInfo as null. Not even the log line you added prints on the console.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
# 没有任何报错。 $ node verify-schema.mjs Query.orders + shippingInfo: {"orders":[ {"id":"order-456","status":"SHIPPED","shippingInfo":null}, {"id":"order-457","status":"DELIVERED","shippingInfo":null}]} errors: [] # 你在 resolver 第一行加的 console.log('>>> shippingInfo called') # 一次都没打印。# No error at all. $ node verify-schema.mjs Query.orders + shippingInfo: {"orders":[ {"id":"order-456","status":"SHIPPED","shippingInfo":null}, {"id":"order-457","status":"DELIVERED","shippingInfo":null}]} errors: [] # The console.log('>>> shippingInfo called') you added as the resolver's first line # never printed, not once.
JavaScriptsrc/resolvers/orderResolvers.js示意Illustrative
1export const resolvers = {
2 Order: {
3 async shipping(parent, _, { loaders }) { // ← 名字
4 console.log('>>> shippingInfo called');
5 return loaders.shippingInfoLoader.load(parent.id);
6 }
7 },
8 ...
9};
10
11// 参考 schema.graphql:
12// type Order {
13// ...
14// shippingInfo: ShippingInfo
15// }
1export const resolvers = {
2 Order: {
3 async shipping(parent, _, { loaders }) { // ← the name
4 console.log('>>> shippingInfo called');
5 return loaders.shippingInfoLoader.load(parent.id);
6 }
7 },
8 ...
9};
10
11// For reference, schema.graphql says:
12// type Order {
13// ...
14// shippingInfo: ShippingInfo
15// }
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · Federation 十种典型故障Debug Lab · ten common Federation failures · Federation 考试Federation exam
L2Debug LabDebug Lab故障 2 · Cannot return null for non-nullable fieldFault 2 · Cannot return null for non-nullable field

查一个没有订单的用户,整个 data 变成了null,而且 errors 里有一条很长的消息。

You query a user who has no orders, the whole data turns into null, and errors carries one very long message.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
$ node verify-schema.mjs Query.orders: {"orders":null} errors: [{ "message": "Cannot return null for non-nullable field Query.orders.", "path": ["orders"], "extensions": { "code": "INTERNAL_SERVER_ERROR" } }] # 更严重的情况:如果查询是嵌套的,整个 data 会变成 null$ node verify-schema.mjs Query.orders: {"orders":null} errors: [{ "message": "Cannot return null for non-nullable field Query.orders.", "path": ["orders"], "extensions": { "code": "INTERNAL_SERVER_ERROR" } }] # Worse case: if the query is nested, the whole data object turns into null
JavaScriptsrc/resolvers/orderResolvers.js示意Illustrative
1async orders(_, { userId }, { dataSources, correlationId }) {
2 const orders = await dataSources.orderDataSource.getOrdersByUserId(userId);
3 return orders; // 数据源可能返回 undefined
4}
5
6// 参考 schema.graphql:
7// type Query {
8// orders(userId: ID!): [Order!]! ← 双重非空
9// }
1async orders(_, { userId }, { dataSources, correlationId }) {
2 const orders = await dataSources.orderDataSource.getOrdersByUserId(userId);
3 return orders; // the data source may return undefined
4}
5
6// For reference, schema.graphql says:
7// type Query {
8// orders(userId: ID!): [Order!]! ← non-null twice
9// }
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · Federation 十种典型故障Debug Lab · ten common Federation failures · Federation 考试Federation exam
L3Debug LabDebug Lab故障 3 · A 拿到了 B 的数据Fault 3 · A receives B's data

查两个订单的物流,返回的数据对上了错的订单。 没有任何报错。这是 DataLoader 最阴险的一类误用。

You query the shipping info for two orders and the data comes back attached to the wrong order. Nothing reports an error. This is the hardest kind of DataLoader misuse to notice.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
# 没有任何报错。 # 查询:{ orders(userId:"123") { id shippingInfo { trackingNumber } } } # # 期望: # order-456 -> TRACK123456 # order-457 -> TRACK123457 # # 实际: # order-456 -> TRACK123457 ← 串了! # order-457 -> null # 日志:[DataLoader] Batching 2 shipping info requests ← 合并是生效的# No error at all. # Query: { orders(userId:"123") { id shippingInfo { trackingNumber } } } # # Expected: # order-456 -> TRACK123456 # order-457 -> TRACK123457 # # Actual: # order-456 -> TRACK123457 ← got the other one's number! # order-457 -> null # Log: [DataLoader] Batching 2 shipping info requests ← the batching does work
JavaScriptsrc/resolvers/orderResolvers.js示意Illustrative
1function createShippingInfoLoader(shippingDataSource) {
2 return new DataLoader(async orderIds => {
3 console.log(`[DataLoader] Batching ${orderIds.length} shipping info requests`);
4
5 const all = await Promise.all(
6 orderIds.map(id => shippingDataSource.getShippingInfo(id))
7 );
8
9 // 「过滤掉没有物流信息的」—— 看起来很合理
10 return all.filter(info => info !== null);
11 });
12}
1function createShippingInfoLoader(shippingDataSource) {
2 return new DataLoader(async orderIds => {
3 console.log(`[DataLoader] Batching ${orderIds.length} shipping info requests`);
4
5 const all = await Promise.all(
6 orderIds.map(id => shippingDataSource.getShippingInfo(id))
7 );
8
9 // "drop the ones with no shipping info" — this looks reasonable
10 return all.filter(info => info !== null);
11 });
12}
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · Federation 十种典型故障Debug Lab · ten common Federation failures · Federation 考试Federation exam
L2Debug LabDebug Lab故障 4 · PATCH 传了小写状态,返回 500Fault 4 · PATCH sends a lowercase status and gets a 500

Java 那边。mvn test 全过, 但客户端传小写的 shipped 时服务返回 500。

This one is on the Java side. mvn test passes everything, but the service returns 500 when the client sends the lowercase shipped.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
$ curl -i -X PATCH localhost:8080/api/orders/1/status \ -H 'Content-Type: application/json' -d '{"status":"shipped"}' HTTP/1.1 500 {"timestamp":"...","status":500,"error":"Internal Server Error"} # 服务端日志: java.lang.IllegalArgumentException: No enum constant com.techflow.orders.model.OrderStatus.shipped at java.base/java.lang.Enum.valueOf(Enum.java:293) at com.techflow.orders.model.OrderStatus.valueOf(OrderStatus.java:3) at c.t.orders.controller.OrderController.updateOrderStatus(OrderController.java:71) # mvn test:Tests run: 5, Failures: 0 ← 测试全过$ curl -i -X PATCH localhost:8080/api/orders/1/status \ -H 'Content-Type: application/json' -d '{"status":"shipped"}' HTTP/1.1 500 {"timestamp":"...","status":500,"error":"Internal Server Error"} # Server log: java.lang.IllegalArgumentException: No enum constant com.techflow.orders.model.OrderStatus.shipped at java.base/java.lang.Enum.valueOf(Enum.java:293) at com.techflow.orders.model.OrderStatus.valueOf(OrderStatus.java:3) at c.t.orders.controller.OrderController.updateOrderStatus(OrderController.java:71) # mvn test: Tests run: 5, Failures: 0 ← every test passes
JavaOrderController.java示意Illustrative
1@PatchMapping("/api/orders/{id}/status")
2public ResponseEntity<Order> updateOrderStatus(
3 @PathVariable Long id,
4 @RequestBody Map<String, String> statusUpdate) {
5 OrderStatus status = OrderStatus.valueOf(statusUpdate.get("status"));
6 return ResponseEntity.ok(orderService.updateOrderStatus(id, status));
7}
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this