能够中止异步调用 [英] Ability to abort asynchronous call

查看:105
本文介绍了能够中止异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将babeljs与es7风格的async/await方法一起使用.我有一个主脚本,该脚本将对全部返回promise的对象数组调用异步方法.我使用Promise.all()等待所有这些返回,但是,这些任务可能会花费很长时间,并且如果它们超过阈值,我想中止所有这些任务,并且该任务将以适当的方式进行处理.

I'm using babeljs with es7 style async/await methods. I have a main script that will call a async method on an array of objects that all return promises. I use Promise.all() to wait for all of those to return, however, these tasks could take a long time and if they exceed a threshold I would like to abort all of them, and the task handle that in an appropriate way.

反正有做这样的事情吗?目前,我唯一想到的方法是生成一个进程,该进程完成调用这些方法的工作,并等待它们全部解决,并且如果达到了时间限制,它可以终止该进程并进行所需的任何处理.

Is there anyway to accomplish such a thing? Currently the only way that I can think of is by spawning a process that does the work of calling these methods and waiting for them to all resolve, and if the time limit is reach, it can kill the process and do whatever handling it needs.

更新:有关这些主要脚本正在等待的方法的说明...它们可能正在执行一系列的操作(调用外部系统,在某处流送文件等),并且未执行可以取消的单个操作独立地.

Update: Some clarification about these methods that the main script is waiting on... They might be doing a long series of operations (calling external systems, streaming files somewhere, etc) and not performing one single action that could be canceled independently.

更新#2:一些未经测试的半伪代码

Update #2: Some untested semi-psuedo code

class Foo1 {
    async doSomething() {
        // call some external system
        // copy some files
        // put those files somewhere else (s3)
    }
}
class Foo2 {
    async doSomething() {
        // Do some long computations
        // Update some systems
    }
}

class FooHandler {
    constructor() {
        this.fooList = [];
    }

    async start() {
        await Promise.all(this.fooList.map(async (foo) => {
            return await foo.doSomething();
        }));
    }
}

let handler = new FooHandler();

handler.fooList.push(new Foo1());
handler.fooList.push(new Foo2());

// if this call takes too long because of slow connections, errors,   whatever,
// abort start(), handle it in whatever meaningful way, and continue on.
await handler.start();

推荐答案

ES6原生版本当前不直接支持取消.在很多地方一直在谈论它,但是还没有.

Native ES6 promises currently do not support cancellation directly. There are talks about it all the time in many places but it's not there yet.

由于本机promise不支持它,而async/await在promise上运行,因此目前尚没有简便的方法来中止它.一种常见的方法是在创建返回承诺的操作时使用令牌.

Since native promises don't support it and async/await works on promises, there is currently no built in easy way to abort it. One common approach is to use a token when creating the action returning a promise.

假设您已承诺使用XHR GET:

Let's say you've promisified XHR GET:

// simplification
function ajax(url){
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest;
        xhr.open("GET", url);
        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = reject;
        xhr.send();
    });
}

现在您要使用它:

async function foo(){
    let result = await ajax("/myApi");
    let result2 = await ajax("/myApi2?token=" + result);
}

现在,假设我们要在某些情况下取消AJAX,我们可以这样传递令牌:

Now, let's say we want to cancel the AJAX in some cases, we can pass a token as such:

function ajax(url, token = {}){
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest;
        xhr.open("GET", url);
        Object(token).cancel = () => { xhr.abort(), reject(); };
        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = reject;
        xhr.send();
    });
}

这可以让您做到:

async function foo(){
    let token = {};
    let req = ajax("/myApi", token); // note no await
    // now let's say we want to abort the request since we don't 
    // need the data
    token.cancel(); // this will abort the token
}

这种方法需要使用链接才能工作,幸运的是,使用ES6语法并没有什么大不了的.祝你好运,编码愉快.

This approach needs work to work with chaining, luckily with ES6 syntax this is not as big of a deal. Good luck and happy coding.

这篇关于能够中止异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆