Как вернуть разрешающий объект Promise Like из цикла for - PullRequest
0 голосов
/ 04 октября 2018

В моей собственной функции есть объект, похожий на обещание, который расшифровывает данное сообщение, используя web crypto api.Проблема в том, что в моей функции расшифровки я хочу попробовать несколько разных значений в качестве входных данных и выполнить это обещание как объект несколько раз в цикле for, а в конце функция должна вернуть объект, который любое из этих обещаний разрешается успешно.

public decryptMessage(latitude: [string, number], longitude: [string, number], ciphertext: string) {
    //get salt 
    const salt = localStorage.getItem("salt")
    const retrievedSaltArray = JSON.parse(salt)
    const saltBytes = new Uint8Array(retrievedSaltArray)

    //get iv
    const iv = localStorage.getItem("iv")
    const retrievedIvArray = JSON.parse(iv)
    const ivBytes = new Uint8Array(retrievedIvArray)

    //get tolerance distance
    let toleranceDistance = parseInt(JSON.parse(localStorage.getItem("toleranceDistance")))

    //get original keyHash
    let originalHash = localStorage.getItem("keyhash")

    //create location inputs(locations with adjacent quadrants)
    let location = new Location(latitude, longitude)
    let locationInputs = location.prepareReceiverLocationInputs()

    let encryptionTool = new EncryptionHelper(saltBytes, ivBytes)

    for (let i = 0; i <= locationInputs.length - 1; i++) {
        let plaintText = encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash)
        plaintText.then(function (plaintTextResult) {
            return plaintTextResult
        })
    }

}

Итак, вот что я пытаюсь сделать, это обещание Как и ojbect, то есть encryptionTool.decryp () должен выполняться в цикле for, а затем любое из этих обещаний разрешается должно быть возвращаемым значением метода decryptMessage.Однако этот метод encryptionTool.decrypt использует webcrypto api, поэтому у него нет методов отклонения или перехвата, потому что это метод, подобный обещанию.

1 Ответ

0 голосов
/ 04 октября 2018

Поскольку обещание представляет собой значение, которое будет доступно в будущем, вы не можете проверить «сейчас» (синхронно), какое из них выполнено успешно.Вместо этого вы должны использовать доступные функции для управления и комбинирования обещаний.Я предполагаю, encryptionTool.decrypt возвращает PromiseLike<string>;если это PromiseLike<T> для какого-то другого T, просто замените string на T в следующем.

Сначала вы можете использовать Promise.resolve для преобразования PromiseLike<string> в Promise<string>.Затем вы хотите использовать Promise.all, чтобы получить массив обещаний и вернуть обещание массива результатов, чтобы вы могли написать обратный вызов then для сканирования массива и получения нужного результата.Потенциальная проблема заключается в том, что Promise.all отклоняет, если любой из предоставленных обещаний отклоняет, и в этом случае вы не видите других результатов.Поэтому, прежде чем использовать Promise.all, вам необходимо использовать catch, чтобы сопоставить отклонение со значением дозорного, например null.Полный код будет выглядеть примерно так (я не проверял его, поэтому возможны ошибки):

    // Assuming that encryptionTool.decrypt returns a PromiseLike<string>,
    // promises will be a Promise<string | null>[].
    let promises = [];
    for (let i = 0; i <= locationInputs.length - 1; i++) {
        promises.push(
            Promise.resolve(encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash))
            .catch((error) => null));
    }
    return Promise.all(promises).then((results) => {
        // results is a (string | null)[].
        // Look through it, find the non-null result and return it.
    });

Обратите внимание, что последний вызов then генерирует обещание для конечного результата, и высинхронно возвращайте это обещание вызывающей стороне decryptMessage.

Альтернативный подход - сделать decryptMessage асинхронной функцией, чтобы вы могли программировать в более привычном стиле.Замените public decryptMessage на public async decryptMessage, а затем используйте код, подобный следующему:

    for (let i = 0; i <= locationInputs.length - 1; i++) {
        try {
            return await encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash);
        } catch (e) {
            // Discard the exception and proceed to the next decryption attempt.
        }
    }
    // TODO: Decide what to return here if all decryptions fail.

Обратите внимание, что таким образом каждое дешифрование не начинается, пока не произойдет сбой предыдущего, поэтому процесс может занять больше времени в зависимости ото том, как реализован веб-крипто-API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...