[英]How to cancel pending promise calls inside callback function?
fetch(
"https://rqyhfmwv4b.execute-api.us-east-1.amazonaws.com/production/join-meeting",
requestOptions
).then((response) => response.json())
.then(async (data) => {
// You need responses from server-side Chime API. See below for details.
const meetingResponse =
data.result
.meetingResponsee; /* The response from the CreateMeeting API action */
const attendeeResponse =
data.result
.attendeeResponsee; /* The response from the CreateAttendee or BatchCreateAttendee API action */
const configuration = new MeetingSessionConfiguration(
meetingResponse,
attendeeResponse
);
// In the usage examples below, you will use this meetingSession object.
const meetingSession = new DefaultMeetingSession(
configuration,
logger,
deviceController
);
const meetingReadinessChecker = new DefaultMeetingReadinessChecker(
logger,
meetingSession
);
// testing
if (pauseReadinessTest) {
setPauseReadinessTest(false);
return;
}
if (testParam == "All" && disableStartRedinessTest !== true) {
await audioTest(deviceController);
setMeetingTestProgress(15);
await micTest(meetingSession, meetingReadinessChecker, CheckAudioInputFeedback);
setMeetingTestProgress(25);
await videoTest(meetingSession, meetingReadinessChecker, CheckVideoInputFeedback);
await cameraTest(meetingSession, meetingReadinessChecker, CheckCameraResolutionFeedback);
setMeetingTestProgress(50);
await networkTest(meetingReadinessChecker, CheckNetworkTCPConnectivityFeedback, CheckNetworkUDPConnectivityFeedback);
setMeetingTestProgress(75);
await streamTest(meetingSession, meetingReadinessChecker, CheckAudioConnectivityFeedback, CheckVideoConnectivityFeedback);
setMeetingTestProgress(85);
await screenShareTest(meetingSession, meetingReadinessChecker, CheckContentShareConnectivityFeedback);
setMeetingTestProgress(100);
setRefreshIconClass(" ");
SetDisableStartRedinessTest(false);
setIsResult("result");
}
I have this block of code and I want to cancel the pending await function calls if at any point in time the user wants to exit from the test.我有这段代码,如果用户想要退出测试,我想取消挂起的等待函数调用。 But the issue is whenever the value of a variable gets updated it doesn't reflect inside the block which is causing the main issue over here.但问题是,每当变量的值被更新时,它都不会反映在导致主要问题的块内。
As far as I remember, promise concept is mostly a syntax sugar.据我所知,promise 概念主要是一种语法糖。 What happens in real world - you pass a callback function (B) inside a function call (A) and at some moment function A will do a call to function B. If you did not write function A with canceling concept in mind, there is no way to cancel the call.现实世界中会发生什么 - 您在函数调用 (A) 中传递一个回调函数 (B),并且在某个时刻函数 A 将调用函数 B。如果您在编写函数 A 时没有考虑到取消概念,则有没有办法取消通话。 Easier to use some other method (global variable, extra passed object argument, whatever) to set a flag "do not run" and check it inside function B.更容易使用其他方法(全局变量、额外传递的对象参数等)来设置标志“不运行”并在函数 B 中检查它。
You could do something like this:你可以这样做:
const promises = [{
functionCall: () => audioTest(deviceController),
progress: 15,
}, {
functionCall: await micTest(meetingSession, meetingReadinessChecker, CheckAudioInputFeedback),
progress: 25,
}, // ...etc.
];
while (testParam == "All" && disableStartRedinessTest !== true && promises.length) {
const { functionCall, progress } = promises.unshift();
await functionCall.call();
setMeetingTestProgress(progress);
}
Although if you're thinking about cancelling operations, I would use RxJS instead of vanilla promises.虽然如果你正在考虑取消操作,我会使用 RxJS 而不是 vanilla Promise。
If you have a pending promise inside a callback function, you can cancel it by using the Promise.prototype.cancel() method.如果您在回调函数中有待处理的承诺,您可以使用 Promise.prototype.cancel() 方法取消它。 For example:例如:
var promise = new Promise(function(resolve, reject) {
// do something
if (/* some condition */) {
resolve(); // or reject(), depending on your needs
} else {
promise.cancel(); // this will cancel the pending promise and prevent it from being resolved or rejected
}
});
You can try my lib to do the trick, where you just need to use a generator instead of the async function and then wrap it with promisify
method.你可以试试我的 lib 来解决这个问题,你只需要使用生成器而不是 async 函数,然后用promisify
方法包装它。
import { CPromise } from "c-promise2";
import cpAxios from "cp-axios";
// ################# Dummy subtasks #####################
const fakeAsyncTask = (name) =>
new Promise((resolve) => setTimeout(resolve, 2500, name));
const fakeAsyncTaskCancelable = (name) =>
new CPromise((resolve, reject, { onCancel }) => {
const timer = setTimeout(resolve, 2500, name);
onCancel(() => {
console.log(`Task [${name}] onCancel handler`);
clearTimeout(timer);
});
});
// ####### Make a cancellable async function from a generator ############
const task = CPromise.promisify(function* () {
console.log("started");
this.innerWeight(4); // how many steps are expected here (yields)
const { data } = yield cpAxios.get(
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s"
);
console.log("Data:", data);
yield fakeAsyncTask("foo");
console.log("task 1 done");
yield fakeAsyncTaskCancelable("bar");
console.log("task 2 done");
yield fakeAsyncTask("baz");
console.log("task 3 done");
return "It works!";
});
let promise;
const run = () => {
cancel();
promise = task("foo")
.progress((p) => console.log(`Progress: ${p}`))
.then((result) => console.log(`Done: ${result}`));
};
const cancel = () => promise?.cancel("Ooops!");
document.querySelector("#btn-run").onclick = run;
document.querySelector("#btn-cancel").onclick = cancel;
If you want to call the task inside useEffect, you can try another my library:如果要在 useEffect 中调用任务,可以尝试另一个 my library:
import React, { useState } from "react";
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
import { ProgressBar } from "react-bootstrap";
import { fakeAsyncTask, fakeAsyncTaskCancelable } from "./tasks.js";
function TestComponent(props) {
const [text, setText] = useState("");
const [progress, setProgress] = useState(0);
const [cancel, done, result, err] = useAsyncEffect(
function* () {
console.log("started");
this.progress(setProgress);
this.innerWeight(4); // how many steps are expected here (yields)
const { data } = yield cpAxios.get(
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s"
);
console.log(data);
setText("Request done");
yield fakeAsyncTask("foo");
setText("Task foo done");
yield fakeAsyncTaskCancelable("bar");
setText("Task bar done");
yield fakeAsyncTask("baz");
setText("Task baz done");
return "It works!";
},
{ states: true, deps: [props.url] }
);
return (
// ...
<ProgressBar animated now={progress * 100} label={text} />
// ...
<button onClick={cancel} disabled={done}>
Cancel async effect
</button>
);
}
export default TestComponent;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.