繁体   English   中英

如何在回调函数中取消待处理的承诺调用?

[英]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");
}

我有这段代码,如果用户想要退出测试,我想取消挂起的等待函数调用。 但问题是,每当变量的值被更新时,它都不会反映在导致主要问题的块内。

据我所知,promise 概念主要是一种语法糖。 现实世界中会发生什么 - 您在函数调用 (A) 中传递一个回调函数 (B),并且在某个时刻函数 A 将调用函数 B。如果您在编写函数 A 时没有考虑到取消概念,则有没有办法取消通话。 更容易使用其他方法(全局变量、额外传递的对象参数等)来设置标志“不运行”并在函数 B 中检查它。

你可以这样做:

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);
}

虽然如果你正在考虑取消操作,我会使用 RxJS 而不是 vanilla Promise。

如果您在回调函数中有待处理的承诺,您可以使用 Promise.prototype.cancel() 方法取消它。 例如:

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
  }
});

你可以试试我的 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;

如果要在 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.

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