почему мой код выполняется в том порядке, в котором он выполняется - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь использовать обещания, чтобы убедиться, что определенные свойства установлены, прежде чем пытаться использовать эти переменные позже.

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

Создание оболочки функции обещания (я думаю)

function skillPromise(char, opts) {
    return new Promise((res, rej) => {
        skills_api.getCharactersCharacterIdSkills(char.eve_id, opts, (e, r, b) => {
            if (!e) res(r.total_sp);
            else rej(e);
        });
    });
}

Использование обещания

characters.forEach((c) => {
    skillPromise(c, opts).then((spt) => {
        c.totalSP = spt;
        console.log(spt);
        console.log(c.totalSP);
    }).catch(() => {});
});
console.log(characters);

Вывод

первый запуск

[ { eve_id: 123456,
    name: 'name',
    access_token: '',
    refresh_token: '' } ]
4652555
4652555

второй запуск

[ { eve_id: 123456,
    name: 'name',
    access_token: '',
    refresh_token: '',
    totalSP: 4652555
  },
  { eve_id: 654321,
    name: 'eman',
    access_token: '',
    refresh_token: '' } ]
9075602
9075602

Все последующие запуски будут следовать этому шаблону.

Принудительное обновление имеет тот же эффект, что идобавление входа в систему, а также перепечатывание значений ранее.

[ { eve_id: 123456,
    name: 'name',
    access_token:'',
    refresh_token:'',
    totalSP: 4652555 },
  { eve_id: 654321,
    name: 'eman',
    access_token:'',
    refresh_token:'',
    totalSP: 9075602 } ]
9075602
9075602

Я думаю, я просто не понимаю, что я здесь построил.Главным образом это время смущает меня.Почему он делает то, что я ожидаю, но в другом порядке?

РЕДАКТИРОВАТЬ: я закончил добавлять обертки функции обещания к обратным вызовам API и использовал Promise.all() для их разрешения, а затем отображал для него только страницу в тогда.По сути, он делает то, что я хочу сейчас.

Две вещи, которые я узнал при использовании обещания всего:

  1. если у вас есть функции-обертки, вы можете фактически передавать им аргументы дажевнутри promise.all() вызова

  2. вы по-прежнему получаете возвраты, но они находятся в массиве, который передается в .then()

Обещают всем

Promise.all([skillPromise(c, opts), walletPromise(c, opts), locationPromise(c, opts)]).then((returns) => {
    c.totalSP = returns[0];
    c.walletBalance = returns[1];
    c.solarSystem = returns[2];
    res.render('characters', { characters: characters });
}).catch(() => {});

Оболочки функции Обещание:

function skillPromise(char, opts) {
    return new Promise((res, rej) => {
        skills_api.getCharactersCharacterIdSkills(char.eve_id, opts, (e, r, b) => {
            if (!e) res(r.total_sp);
            else rej(e);
        });
    });
}

function walletPromise(char, opts) {
    return new Promise((res, rej) => {
        wallet_api.getCharactersCharacterIdWallet(char.eve_id, opts, (e, r, b) => {
            if (!e) res(r);
            else rej(e);
        });
    });
}

function locationPromise(char, opts) {
    return new Promise((res, rej) => {
        location_api.getCharactersCharacterIdLocation(char.eve_id, opts, (e, r, b) => {
            if (!e) {
                // Translate solar_system_id & station_id into System name and Station Name
                universe_api.getUniverseSystemsSystemId(r.solar_system_id, opts, (e, r, b) => {
                    if (!e) res(r.name);
                    else rej(e);
                });
            } else rej(e);
        });
    });
}

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Я думаю, что это то, что происходит.Сначала вы выполняете функцию обратного вызова forEach, forEach и ставит задачу (которая будет выполняться циклом событий позже, когда закончится текущий скрипт) для каждого вызова обратного вызова (который будет вызываться столько раз, сколько элементов у вас вмассив символов. После постановки этих задач в очередь выполнение сценария переходит к console.log(characters);, и это то, что вы видите напечатанным первым. Теперь выполнение сценария завершено, и цикл обработки событий обрабатывает очередь задач, обрабатывая первые задачи, добавленныеforEach (это одно выполнение функции skillPromise, которая добавляет обещание в очередь микротаз. Это делается для каждой задачи, добавляется цикл forEach. Если при обработке этих задач некоторые обещания будут обработаны, JavaScript будет обрабатывать их.их (не одно, а все обещания, которые разрешены) после обработки текущей задачи, поставленной в очередь * 1007. * Если никакое обещание не будет решено до обработки всех задач, поставленных в очередь forEach, то javascript будет обрабатывать их все впоследствии, когда они будут решены.

Так что порядок, сначала мы еxecute console.log(characters);, затем мы обрабатываем задачи и обещания.

Вы можете проверить это видео, я считаю его хорошим объяснением того, как работает цикл обработки событий javascript.

0 голосов
/ 12 февраля 2019

Вы можете использовать функцию .reduce(), чтобы обернуть каждое обещание в then() предыдущего обещания.

characters.reduce((prevPromise, c) => {
    var promise = skillPromise(c, opts).then((spt) => {
            c.totalSP = spt;
            console.log(spt);
            console.log(c.totalSP);
        }).catch(() => {});

    if(prevPromise == null){
        return promise;
    }else{
        prevPromise.then(promise)
    }
}, null);
...