【问题标题】:why does my code execute in the order it does为什么我的代码按顺序执行
【发布时间】:2019-07-05 19:43:25
【问题描述】:

我正在尝试使用承诺来确保在稍后尝试使用这些变量之前设置某些属性。

我已经设法拼凑出一些代码,这些代码似乎可以做我想做的事,但考虑到我对 Promise 的了解,这并不是我期望的顺序。

创建 promise 函数包装器(我认为)

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

我想我只是不明白我在这里构建了什么。 主要是它让我感到困惑的时间。 为什么它会按照我的预期执行,但顺序不同?

编辑: 我完成了将 promise 函数包装器添加到 API 回调并使用 Promise.all() 来解决它们,然后只在 then 中呈现页面。基本上,它可以满足我现在的需求。

我在使用 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(() => {});

Promise 函数包装器:

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);
        });
    });
}

【问题讨论】:

  • Promises 准备好后立即异步解析。因此执行顺序与解析顺序不同。
  • 嗨,请查看 Promise.all 这应该对 foreach 有所帮助。

标签: javascript promise order-of-execution


【解决方案1】:

我认为这就是正在发生的事情。 首先,您执行forEachforEach 的回调将任务排队(在当前脚本完成后由事件循环稍后执行)对于回调的每次调用(将被调用的次数与您在其中的元素一样多)字符数组。在对这些任务进行排队之后,脚本的执行继续到console.log(characters);,这就是您首先看到的打印内容。现在脚本执行完成并且事件循环进入处理任务队列,它处理由添加的第一个任务forEach(这是函数skillPromise的一次执行,它向微任务队列添加了一个promise。它为每个添加了forEach循环的任务执行此操作。如果在处理这些任务时,一些promise得到解决,javascript将处理在处理由forEach 排队的当前任务之后,它们(不是一个,而是所有已解决的承诺)。如果在处理forEach 排队的所有任务之前没有解决任何承诺,javascript 将在它们被解决后处理所有它们。

所以顺序是,首先我们执行console.log(characters);,然后我们处理任务和承诺。

您可以查看this 视频,我发现它很好地解释了 javascript 事件循环的工作原理。

【讨论】:

    【解决方案2】:

    您可以使用.reduce() 函数将每个promise 包装在前一个promise 的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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多