Javascript 我可以依赖非链接的后续订单吗?

Javascript 我可以依赖非链接的后续订单吗?,javascript,promise,Javascript,Promise,众所周知,一个人可以将多个承诺组合成一个链,从而一个接一个地调用oncompleted回调(尽管它们彼此是异步的): 但是,无链的后续承诺又如何呢? 最简单的例子是: Promise.resolve() .then(() => console.log("i will be the first one")) ; Promise.resolve() .then(() => console.log("i will be the second one")) // sure? ;

众所周知,一个人可以将多个承诺组合成一个链,从而一个接一个地调用
oncompleted
回调(尽管它们彼此是异步的):

但是,无链的后续承诺又如何呢? 最简单的例子是:

Promise.resolve()
   .then(() => console.log("i will be the first one"))
;
Promise.resolve()
   .then(() => console.log("i will be the second one"))  // sure?
;
我天真的认为,Promise回调通过事件队列(大约类似于
setTimeout
中的计时器事件)工作,这样一来,第一个
Promise.resolve()
在第二个回调之前将其事件推送到队列中,因此第一个回调将在第二个回调之前被调用

但我不确定是否有任何保证。我可以依赖它吗?或者它是异步乐透?有人知道规格说明了什么吗

更新

你们中的一些人注意到,最简单的例子是无用的,所以我想解释一下我原来的问题

我有一个类,它惰性地初始化另一个类的实例,并为托管实例提供get方法:

class Lazy {

    /** @param {Class} T */
    constructor(T) { }

    /** @returns {Promise.<T>} */
    instance() { 
       // there will be complex async initialization at first call
       // and Promise.resolve() at following calls
    }
}

class Foo {
   on() { }
   off() { }
}

/** @type {Lazy.<Foo>} */
let foo = new Lazy(Foo);

foo.instance().then((i) => i.on());
foo.instance().then((i) => i.off());
类延迟{
/**@param{Class}T*/
构造函数(T){}
/**@returns{Promise.}*/
实例(){
//第一次调用时将进行复杂的异步初始化
//和Promise.resolve()进行以下调用
}
}
福班{
关于(){}
off(){}
}
/**@type{Lazy.}*/
设foo=newlazy(foo);
然后((i)=>i.on());
foo.instance().then((i)=>i.off());
最后两行揭示了我的问题-当我不确定
on()
是否会在
off()之前调用
on()
时,很难以这种方式使用
Foo
实例

承诺回调通过事件队列工作

这不是真的。回调以先返回先服务的方式工作。启动操作时的顺序并不重要,它们返回的顺序决定了将首先处理哪个操作

在您的示例中,如果“第一个”异步操作比“第二个”异步操作花费更长的时间返回,那么“第二个”
将首先处理


显然,这些操作需要多长时间才能返回有很多变量。网络速度、服务器上的负载(或您使用的任何异步服务)、promise引擎的浏览器实现等等。因此您必须假设您不知道这些将在何时处理

为了避免竞态条件,如果您需要某种特定的顺序,那么使用回调/
。然后
/
等待
/etc以确保它们按该顺序运行。您不能依赖于调用操作的顺序。

您的实际问题: 最后两行揭示了我的问题——当我不确定在off()之前是否会调用on()时,很难用这种方式处理foo实例

您不应该依赖此行为,而是应该
等待
获取实例,然后缓存它:

async function withInstance() {
  let instance = await foo.instance();    
  await instance.on();
  await instance.off(); // guaranteed to be called after `.on`.
}
你问的 您可以依赖作业的执行顺序

如果添加了承诺
,则它是规范中的一个引用:

来自单个作业队列的挂起作业记录始终以FIFO顺序启动

注意:如果您有多个上下文(例如,iFrame或Worker之间的不同承诺),则此保证不成立


也就是说,强烈建议不要依赖这样的执行顺序。

这可能会对您有所帮助,您为什么要这样做?似乎您正试图摆脱承诺的目的,即允许异步响应。如果您试图获得类似于
setTimeout(…,0)
的行为,请使用
setTimeout
。如果您想保证订单,请使用
async
-
wait
。如果您有即时返回的同步事件,请不要使用承诺。
确定?
-是的,您可以确定您是否也考虑过
const p=Promise.resolve();p、 然后(()=>console.log(“我将是第一个”);p、 然后(()=>console.log(“我将是第二个”)整个问题非常不重要,因为如果没有实际的异步操作,那么首先就不要使用承诺。如果您确实有异步操作,那么完成顺序总是不确定的(除非底层的两个操作以某种方式相互关联)。所以,谁在乎两个
Promise.resolve()
调用是否按顺序提供呢。在你的代码中,它永远都不重要。如果是这样的话,就用不同的代码来保证订单!“您不知道这些将在什么时候被处理。”-事实上,您知道,这是由语言规范保证的。不过,依赖它并不是一个好主意。我扩展了我的粗体字,整句话是你必须假设你不知道这些信息何时会被处理。:)@本贾明鲁恩鲍姆
async function withInstance() {
  let instance = await foo.instance();    
  await instance.on();
  await instance.off(); // guaranteed to be called after `.on`.
}