【问题标题】:Calling asynchronous functions with more asynchronous functions inside调用内部有更多异步函数的异步函数
【发布时间】:2018-11-17 12:44:51
【问题描述】:

我在尝试调用数组内的异步函数链时遇到问题。当我单独调用该函数时,它可以正常工作,如下例所示:

function consoleAll(string) {
    return new Promise(function (resolve) {
        console1(string).then(function () {
            console2(string).then(function () {
                resolve();
            });
        });
    });
}
function console1(value) {
    return new Promise((resolve) => {
        console.log(value + "1");
        resolve()
    });
}
function console2(value) {
    return new Promise((resolve) => {
        console.log(value + "2");
        resolve()
    });
}
consoleAll('value-')

在这种情况下,结果是正确的:

value-1
value-2

但是当它在循环中传递时,它不会正确地使线程并完全无序地调用函数

function consoleAll(string) {
    return new Promise(function (resolve) {
        console1(string).then(function () {
            console2(string).then(function () {
                resolve();
            });
        });
    });
}
function console1(value) {
    return new Promise((resolve) => {
        console.log(value + "1");
        resolve()
    });
}
function console2(value) {
    return new Promise((resolve) => {
        console.log(value + "2");
        resolve()
    });
}

//Call
['h1-', 'h2-', 'h3-'].forEach(function (string) {
  consoleAll(string)
});

这次不是写下面的结果:

h1-1
h1-2
h2-1
h2-2
h3-1
h3-2

它输出这个:

h1-1
h2-1
h3-1
h1-2
h2-2
h3-3

看起来它为整个数组调用了console1函数,然后调用了console2。

有人知道打这个电话的正确方法吗? PS。我不在乎是否需要安装一些插件来解决这个问题。

【问题讨论】:

  • 这段代码使用了 Promise 构造函数反模式...

标签: javascript node.js loops asynchronous promise


【解决方案1】:

你必须再次调用logAll之前的异步调用完成:

const values =  ['h1-', 'h2-', 'h3-'];
(function next(i) {
   if(i >= values.length) return;
   consoleAll(values[i]).then(function() {
      next(i + 1);
   });
})(0);

或者如果这太难看,这里有一个更现代的方法:

(async function() {
   for(const string of ["h1-", "h2-", "h3"])
     await consoleAll(string);
})();

正如我在 cmets 中指出的,consoleAll 最好写成:

function consoleAll(str) {
  return console1(str).then(function() {
    return console2(str);
  });
}

或:

async function consoleAll(str) {
  await console1(str);
  await console2(str);
}

【讨论】:

  • 非常感谢,它真的救了我。我已经为这个问题奋斗了将近一天。
  • @kanzas 很高兴为您提供帮助 :)
【解决方案2】:

如果你调用new Promise(fn),里面的fn会立即被执行。所有的 .then 都被压入堆栈以供稍后执行,但首先整个 .forEach 必须通过。

你可以在这段代码中看到更多:

function consoleAll(string) {
    return new Promise(function (resolve) {
        consoleLog(string, 1).then(function () {
            consoleLog(string, 2).then(function () {
                resolve();
            });
        });
        consoleLog(string, 3).then(function () {
            consoleLog(string, 4).then(function () {
                resolve();
            });
        });
    });
}
function consoleLog(value, tag) {
    return new Promise((resolve) => {
        console.log(value + tag);
        resolve()
    });
}

//Call
['h1-', 'h2-', 'h3-'].forEach(function (string) {
  consoleAll(string)
});

initialition 之后,其余的promise 被随机执行。还请记住,resolve() 不会停止您在函数中执行的任何内容。会被执行!然而,一旦你调用 Promise,Promise 就会从 Pending 变为 Resolved,并且它总是会返回 resolve 中的第一个值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2018-09-06
    • 1970-01-01
    • 2021-02-20
    • 2013-12-07
    相关资源
    最近更新 更多