如何将 Array.prototype.some() 与异步函数一起使用?

JBi*_*Bis 5 javascript asynchronous async-await

我正在尝试执行以下操作:

command.permissions.some(async permissionsKey => {
        switch (permissionsKey) {
            case "all": {
                return true;
            }
            case "OWNER": {
                return await msg.roomContext.isRoomOwnerId(msg.getStaticUserUID());
            }
            default: {
                return config.users_groups[permissionsKey].includes(msg.getStaticUserUID());
            }
        }
    });
Run Code Online (Sandbox Code Playgroud)

然而,它总是正确的,因为 Array.prototype.some 不期望异步函数,因此在调用该函数时会返回一个 promise。Promise 是真实的。

我想知道将异步函数与任何 Array.prototype 函数一起使用的最佳方法,特别是 some 函数。

ant*_*oni 7

我来这里寻找类似的用途,然后发现这篇很棒的文章介绍了这个手动 asyncSome 函数: https: //advancedweb.hu/how-to-use-async-functions-with-array-some-and-every-in- javascript/

当谓词返回真值时,它也会中断循环:

const arr = [1, 2, 3];

const asyncSome = async (arr, predicate) => {
    for (let e of arr) {
        if (await predicate(e)) return true;
    }
    return false;
};

// Example of use for this function:
const res = await asyncSome(arr, async (i) => {
    console.log(`Checking ${i}`);
    await sleep(10);
    return i % 2 === 0;
});
Run Code Online (Sandbox Code Playgroud)

应用到这个用例,它就是:

asyncSome(command.permissions, async permissionsKey => {
        switch (permissionsKey) {
            case "all": {
                return true;
            }
            case "OWNER": {
                return await msg.roomContext.isRoomOwnerId(msg.getStaticUserUID());
            }
            default: {
                return config.users_groups[permissionsKey].includes(msg.getStaticUserUID());
            }
        }
    });
Run Code Online (Sandbox Code Playgroud)

这就像OP建议的方式一样简单。


Ry-*_*Ry- 5

如果您希望在第一个承诺解决后立即获得结果true,您也可以这样做:

const somePromise = promises =>
    new Promise((resolve, reject) => {
        let resolveCount = 0;
        const resolved = value => {
            if (value) {
                resolve(true);
            } else if (++resolveCount === promises.length) {
                resolve(false);
            }
        };

        for (const promise of promises) {
            promise.then(resolved, reject);
        }
    });
Run Code Online (Sandbox Code Playgroud)

另一种花哨的方法:

const never = new Promise(() => {});

const somePromise = promises => Promise.race([
    Promise.race(promises.map(async p => !!await p || never)),
    Promise.all(promises).then(r => r.some(Boolean)),
]);
Run Code Online (Sandbox Code Playgroud)

但是,在您的特定情况下,由于最多只有一个承诺,因此有更好的方法来做到这一点:

let hasPermission =
    command.permissions.some(permissionsKey => {
        switch (permissionsKey) {
            case "all":
                return true;
            case "OWNER":
                return false;
            default:
                return config.users_groups[permissionsKey].includes(msg.getStaticUserUID());
        }
    });

if (!hasPermission && command.permissions.includes("OWNER")) {
    hasPermission = await msg.roomContext.isRoomOwnerId(msg.getStaticUserUID());
}
Run Code Online (Sandbox Code Playgroud)

  • 所以它的效率或速度,你不能两者兼得。好,谢谢。 (2认同)