关于JavaScript中承诺的几个问题

关于JavaScript中承诺的几个问题,javascript,promise,Javascript,Promise,我对JavaScript中的承诺行为感到困惑,有一些问题,有人能帮我解决吗 这是创造承诺的两种常见方式 function promise(){ return new Promise((resolve, reject) => { resolve()}); } let promise = new Promise(function(resolve, reject){ resolve(); }); 第一个函数创建一个Promise对象,但在调用该函数之前不会调用

我对JavaScript中的承诺行为感到困惑,有一些问题,有人能帮我解决吗

这是创造承诺的两种常见方式

function promise(){
    return new Promise((resolve, reject) => {
        resolve()});
}

let promise = new Promise(function(resolve, reject){
    resolve();
});
第一个函数创建一个Promise对象,但在调用该函数之前不会调用它。相比之下,第二条语句创建一个Promise对象并立即调用它。我说得对吗

对于此功能:

function timeout(ms){
    return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'done');
});
}

timeout(100).then((value) => {
    console.log(value);
});
我认为当我们调用timeout函数时,它首先创建一个异步函数setTimeout,并将其推到事件队列的尾部。所有同步事件完成后,将调用它并创建承诺对象。Promise对象也将被推送到事件队列的尾部,该队列位于其他同步事件之后。所以似乎有两个事件循环,对吗

这两种说法相等吗

let promise = new Promise(function(resolve, reject){
    resolve();
});

let promise = Promise.resolve();
为什么输出序列如下所示

setTimeout(function(){
    console.log('3');
}, 0);

Promise.resolve().then(function(){
    console.log('2');
});

console.log('1');

// 1
// 2
// 3
这是一本书中的一个例子,作者解释如下:setTimeoutfn,0将在下一个事件循环开始时调用,Promise.resolve将在当前事件循环结束时调用,console.log将立即调用

我不明白为什么会在下一个事件循环开始时调用setTimeout函数。我认为它也是一个异步函数,将被推送到当前事件队列的末尾,因此应该在Promise对象之前调用它。有人能告诉我为什么我错了吗


如果您使用的是new Promise,这意味着您调用的构造函数将在定义数据类型时首先执行,并且当您将Promise定义为函数时,您需要调用它

不,函数在您调用它之前不会创建承诺。 该承诺将在调用timeout100时创建,并在setTimeout时解析。不确定事件队列的详细信息。 在控制台中似乎如此尝试。 当然要看这一分钟11:30左右。 第一个函数创建一个Promise对象,但在调用该函数之前不会调用它。相比之下,第二条语句创建一个Promise对象并立即调用它。我说得对吗

第一个函数只是一个函数。只要不被称为承诺,就不会产生承诺。一旦它被调用,与作为替代方案的直接执行没有多大区别

我认为当我们调用timeout函数时,它首先创建一个异步函数setTimeout

未创建setTimeout,该函数作为内置函数存在。你可以说它叫

。。。并将其推到事件队列的尾部

推送到队列的不是函数setTimeout本身。在这种情况下,它是回调解析,包括参数、超时时间和放在活动计时器列表中的唯一计时器ID

所有同步事件完成后,将调用它并创建承诺对象

Promise对象是在调用timeout函数期间创建的

传递给新承诺的回调通常称为承诺构造函数回调,在执行新承诺的那一刻,回调也会同步执行并创建承诺

当同步代码完成时,即调用堆栈为空时,首先使用微任务队列。在这个阶段,那里什么都没有,因此任务队列将被验证。如果此时活动计时器已过期,则任务队列中将有该计时器的条目

Promise对象也将被推送到事件队列的尾部,该队列位于其他同步事件之后

承诺对象未放入任何队列中。计时器到期时,队列事件将作为新任务触发,即调用resolve函数,该函数将解析承诺,承诺将在微任务队列中放入条目,每个条目一个,然后回调并等待相关效果。在从任务队列中提取任何其他任务之前,微任务队列将在同一个宏任务中进行处理

所以似乎有两个事件循环,对吗

至少两个;可以有更多。例如,在浏览器上下文中,可能还有另一个与DOM元素突变有关的事件队列。 另请参阅一些不同规格的说明

这两种说法相等吗? 实际上是的;Promise.resolve是newpromiser=>r的缩写

为什么输出序列如下所示

setTimeout(function(){
    console.log('3');
}, 0);

Promise.resolve().then(function(){
    console.log('2');
});

console.log('1');

// 1
// 2
// 3
setTimeout涉及一个任务队列,而。然后涉及一个微任务队列,它总是在处理任务队列之前使用;至少这是当前实现中的共识

补遗 以下是对以下代码事件顺序的一些说明:

function timeout(ms){
    return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'done');
    });
}

timeout(100).then((value) => {
    console.log(value);
});
首先解析代码并创建一个任务来执行它:

任务1 函数超时定义为一个提升变量,函数为 价值 使用参数100调用超时 创建promise对象并同步调用构造函数回调。这两个参数由系统提供。它们是我们的内在功能,当承诺变成履行或拒绝的状态时,我们可以调用它们,由我们来决定。 调用setTimeout。 传递给setTimeout的参数用于在内部计时器列表中创建条目。 将返回计时器的ID,但您的代码不使用返回值。 创建的承诺对象将返回给超时调用方 调用方调用此承诺的then方法,向其传递一个anynomous函数,即带有console.log的函数 promise内部实现将此函数存储在队列中,而不是事件队列中,以便以后可能执行 到达代码末尾时,调用堆栈为空 将检查微任务队列中是否有任何条目,但它也是空的 在背景中: 计时器过期,一个条目被推送到任务队列。它是对传递给setTimeout的函数的挂起调用,在本例中是resolve。具体如何实现取决于实现。 其本质是,在某个点上,任务队列具有可以使用的任务。 任务2 找到并处理任务队列中要调用解析的条目 决议被称为 实现此解析函数的承诺内部将承诺标记为已解析 promise内部构件在微任务队列中创建条目:每个条目对应一个,然后回调或等待它存储在其内部队列中。 在本例中,只有一个这样的条目:在代码中传递给only then方法的匿名函数。 调用堆栈为空—这只是一个要解析的调用 将检查微任务队列中的任何条目,其中有一个条目: 任务2,微任务1 使用微任务队列中的单个条目 调用匿名函数 执行console.log 控制台实现生成输出 调用堆栈为空 微任务队列中没有更多的条目
任务队列中没有更多的条目。系统继续检查任务队列中的新条目。

关于1,调用新承诺时将创建承诺实例。第一种方法创建一个函数,在调用时会执行此操作,第二种方法只是直接创建一个承诺。这一事实与承诺的工作方式无关,新日期也是如此。是的,不是,是的,有多个事件队列一个用于任务,一个用于Mikrotask一个节点。甚至还有更多的SetTimeOutfn,0;实际上是一个setTimeOutn,10;setTimeout不支持10毫秒以下的超时+这不是10毫秒内的呼叫fn,而是更多的呼叫fn只要你有不少于10毫秒的时间,Philip Roberts的可能副本就不会在他的视频中谈论导致第四个示例中奇怪行为的微任务Hi trincot,非常感谢你的回答。我对问题1、3和4已经很清楚了,但仍然对问题2感到有点困惑。创建Promise对象、调用setTimeout函数、解析Promise并运行Promise-then的回调函数的顺序是什么?正如您前面所说,是调用timeout->Promise-be-create->setTimeout-be-call->Promise-be-solution->Promise-then的回调函数吗?oops,再多问一点问题1。正如您所说,当调用promise函数时,将调用promise构造函数回调。您的意思是立即调用promise构造函数回调,而不是将其推送到宏任务或微任务上吗?等着以后再打电话?除此之外,我还不明白“分辨率”到底是什么意思,它是一个函数还是其他什么?resolve会被视为一项任务吗?我在回答中添加了一个部分,我认为这将澄清所有这些要点。当您像调用任何函数一样调用函数resolve时,它会立即执行,但在代码的其他地方,您只能异步注意到承诺已被解析,因为resolve不会同步调用您可能有的then回调。相反,resolve会延迟微任务队列中的那些调用。我已经描述了这个过程。