14

私はes7スタイルのasync/awaitメソッドでbabeljsを使用しています。すべてが promise を返すオブジェクトの配列に対して async メソッドを呼び出すメイン スクリプトがあります。Promise.all() を使用してそれらすべてが戻るのを待ちますが、これらのタスクには時間がかかる可能性があり、しきい値を超えた場合はすべてを中止し、タスクはそれを適切な方法で処理します。

とにかくそのようなことを達成することはありますか?現在、私が考えることができる唯一の方法は、これらのメソッドを呼び出す作業を行うプロセスを生成し、それらがすべて解決されるのを待つことです。制限時間に達した場合、プロセスを強制終了し、必要な処理を行うことができます。

更新: メイン スクリプトが待機しているこれらのメソッドに関するいくつかの明確化...それらは長い一連の操作 (外部システムの呼び出し、どこかでのファイルのストリーミングなど) を実行しており、個別にキャンセルできる単一のアクションを実行していない可能性があります。

更新 #2: テストされていない半疑似コード

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();
4

3 に答える 3

13

ネイティブ ES6 promise は現在、キャンセルを直接サポートしていません。多くの場所でそれについての話が常にありますが、まだそこにはありません。

ネイティブの promise はそれをサポートしておらず、async/await は promise で機能するため、現在、それを中止する簡単な方法は組み込まれていません。一般的なアプローチの 1 つは、promise を返すアクションを作成するときにトークンを使用することです。

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 をキャンセルしたいとしましょう。トークンを次のように渡すことができます。

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 構文ではこれはそれほど大きな問題ではありません。幸運と幸せなコーディング。

于 2015-04-12T18:10:06.550 に答える