Как правильно обрабатывать серию вызовов asyn c внутри родительского вызова asyn c - PullRequest
0 голосов
/ 01 марта 2020

У меня есть сценарий использования, когда я хочу сделать асин c вызов (рассмотрим его как ajax), а затем в успешном блоке этого вызова я хочу сделать серию асин c вызовов в oop используя идентификатор, который генерируется родительским вызовом. Мои требования:

  1. Где я могу разместить код показа тоста успеха? В настоящее время я помещаю его после блока l oop в блоке success, но проблема в том, что он будет выполнен до того, как дочерние асин c вызовы будут завершены, поскольку l oop не будет ждать вызовов и будет выполняются в кратчайшие сроки, и код будет go показывать тост успеха.
  2. Если какой-либо из дочерних вызовов завершится неудачно, дальнейших вызовов не должно произойти (это больше с точки зрения эффективности) , а также в таком случае, я должен быть в состоянии удалить родительскую запись, которая была создана, так как с этим справиться? Заранее спасибо!

Пример кода:

asyncCallA(inputId)
    .then(output => {
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        inputIdsForChildCalls = [do something with output]
        for (let i = 0; i < inputIdsForChildCalls.length; i++) {
            asyncCallB(inputIdsForChildCalls[i])
                .then(output => {
                    // do something
                })
                .catch(error => {
                    // do something with error
                });
        }
        showSuccessToast("Records created successfully!");
    })
    .catch(error => {
        // do something with error
    });

Ответы [ 4 ]

1 голос
/ 01 марта 2020

Поскольку звучит так, как будто вы хотите запустить asyncCallB() последовательно, чтобы вы могли избежать любых дополнительных вызовов в случае сбоя одного из них, тогда это будет проще всего реализовать с помощью async/await.

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

async function someFunc(inputId) {
    try {
        let output = await asyncCallA(inputId);
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        let inputIdsForChildCalls = [do something with output]
        for (let childId of inputIdsForChildCalls) {
            let childResult = await asyncCallB(inputIdsForChildCalls[childId]);
            // process child result here
            // errors in asyncAllB() will have gone to the catch(e) statement below
        }
        showSuccessToast("Records created successfully!");
    } catch(e) {
        // handle error here
        // throw an error here if you want the caller to be able to see the error
    }
}

Для возможно более высокой производительности вы можете запускать операции asyncCallB() параллельно, как показано ниже, но все вызовы asyncCallB() будут выполняться , даже если первый из них имеет ошибку (поскольку все они запускаются параллельно):

async function someFunc() {
    try {
        let output = await asyncCallA(inputId);
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        let inputIdsForChildCalls = [do something with output]
        let allResults = await Promise.all(inputIdsForChildCalls.map(childId => {
            return asyncCallB(childId);
        }));
        // process allResults array here
        // errors will have gone to the catch(e) statement below
        showSuccessToast("Records created successfully!");
    } catch(e) {
        // handle error here
    }
}
0 голосов
/ 01 марта 2020
asyncCallA(inputId)
    .then(output => {
        inputIdsForChildCalls = [do something with output]
        let syncCalls = [];
        for (let i = 0; i < inputIdsForChildCalls.length; i++) {
            syncCalls.push(asyncCallB(inputIdsForChildCalls[i]));
        }
        Promise.all(inputIdsForChildCalls)
           .then(outputs => {
            // do something
            showSuccessToast("Records created successfully!");
           })
        .catch(error => {
            // do something with error
        });
    })
    .catch(error => {
        // do something with error
    });
0 голосов
/ 01 марта 2020

Наилучшим вариантом для обеспечения того, чтобы произошло асинхронное соединение c, является использование функции array.reduce, приведенной ниже, для примера того же кода.

, если вы не знаете, как работает array.reduce и обещать работу. Я бы посоветовал вам обратиться к этой статье.

https://developers.google.com/web/fundamentals/primers/promises

Ниже приведен пример кода, который вы можете использовать.

asyncCallA(inputId)
    .then(output => {
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        inputIdsForChildCalls = [];

        inputIdsForChildCalls.reduce(function(sequence, Id)
        {
            return sequence.then(function()
          {
             return asyncCallB(Id);
          }).then(function(asyncCallResult)
                {
              //do something
        });
        }, Promise.resolve())

    })
    .then(function()
    {
        showSuccessToast("Records created successfully!");
    })
    .catch(error => {
        // do something with error
    });
0 голосов
/ 01 марта 2020
asyncCallA(inputId)
.then(output => {
    inputIdsForChildCalls = [do something with output]
    Promise.all(inputIdsForChildCalls)
        .then(outputs => {
            // do something
            showSuccessToast("Records created successfully!");
        })
        .catch(error => {
            // do something with error
        });
    }
})
.catch(error => {
    // do something with error
});
...