Javascript 承诺链是如何开始和结束的

Javascript 承诺链是如何开始和结束的,javascript,promise,es6-promise,Javascript,Promise,Es6 Promise,我对我遇到的各种文档中的排序方式有点困惑。比如说,我见过这种事情 let p = Promise.resolve(); for (let x in something) { /* do some hairy time consuming code */ p = p.then(dosomething(x)); } return p.then(finalthing()).catch(pretendnobadthing()); 我真的不明白的是,如果你在主代码中做了一些需要花费大量时

我对我遇到的各种文档中的排序方式有点困惑。比如说,我见过这种事情

let p = Promise.resolve();
for (let x in something)
{
    /* do some hairy time consuming code */
    p = p.then(dosomething(x));
}
return p.then(finalthing()).catch(pretendnobadthing());
我真的不明白的是,如果你在主代码中做了一些需要花费大量时间的事情,这难道不意味着其中一个承诺可以在主代码真正开始建立

你能一直使用.then/.catch来实现一个承诺吗?如果它已经完成了,那么它将从它到达的那一点继续进行,所以从概念上看,它就像一条大链,将在某个不确定的点运行到完成?如果是这样的话,那不是意味着每次你创建一个承诺链时,它都会永远挂着吗

我真的不明白的是,如果你在主代码中做了一些需要花费大量时间的事情,这难道不意味着其中一个承诺可以在主代码真正开始建立

因为JavaScript的普通实现从来不会并行运行,所以不会

你能一直使用.then/.catch来实现一个承诺吗?如果它已经完成了,那么它将从它到达的那一点继续进行,所以从概念上看,它就像一条大链,将在某个不确定的点运行到完成

对!!这是承诺的一大优势。以此为例:

var promise = Promise.resolve(5); // already resolved here

setTimeout(function () {
    promise.then(function (x) {
        console.log(x); // still logs 5
    });
}, 1000);
如果是这样的话,那不是意味着每次你创建一个承诺链时,它都会永远挂着吗

在它被解决之前,是的,但是如果承诺已经被解决,并且没有办法再引用它,它可以像任何其他对象一样被处理

我真的不明白的是,如果你在主代码中做了一些需要花费大量时间的事情,这难道不意味着其中一个承诺可以在主代码真正开始建立

因为JavaScript的普通实现从来不会并行运行,所以不会

你能一直使用.then/.catch来实现一个承诺吗?如果它已经完成了,那么它将从它到达的那一点继续进行,所以从概念上看,它就像一条大链,将在某个不确定的点运行到完成

对!!这是承诺的一大优势。以此为例:

var promise = Promise.resolve(5); // already resolved here

setTimeout(function () {
    promise.then(function (x) {
        console.log(x); // still logs 5
    });
}, 1000);
如果是这样的话,那不是意味着每次你创建一个承诺链时,它都会永远挂着吗

在它被解决之前,是的,但是如果承诺已经被解决,并且没有办法再引用它,它可以像任何其他对象一样被处理

你能一直使用.then/.catch来实现一个承诺吗?如果它已经完成了,那么它将从它到达的那一点继续进行,所以从概念上看,它就像一条大链,将在某个不确定的点运行到完成

是的,你可以随时使用。然后/。兑现承诺。调用
p.then()
时,有三种可能

  • 承诺
    p
    仍悬而未决(尚未履行或拒绝)。如果是这种情况,那么传递给
    .then()
    的函数引用将注册为该承诺的侦听器。因此,当承诺发生未来状态转换时(从pending=>Completed或从pending=>rejected),将调用相应的注册侦听器

  • 该承诺已兑现。如果是这种情况,则调用
    。然后(f1,f2)
    将安排
    f1
    在下一次勾选时调用(在当前Javascript片段完成执行后),并将保存的解析值传递给它

  • 承诺
    p
    已被拒绝。如果是这种情况,那么调用
    。然后(f1,f2)
    将安排
    f2
    在下一次勾选时调用(在当前Javascript片段完成执行之后),并将保存的拒绝原因传递给它

  • 因此,对已经履行或拒绝的承诺调用
    .then()
    是完全安全的。适当的侦听器将被安排在下一次运行

    同样的逻辑也适用于
    .catch()
    ,只是它只对上述情况1和3感兴趣

    这是

    如果是这样的话,那不是意味着每次你创建一个承诺链时,它都会永远挂着吗

    承诺和Javascript中的任何其他对象一样都是对象。只有当其他代码仍然有一些对它们的实时引用时,它们才会挂起。一旦无法再访问promise对象,它们就可以像Javascript中的任何其他对象一样进行垃圾收集

    因此,如果你这样做:

    var p = somePromiseReturningFunction();
    
    p.then(f1).then(f2).then(f3);
    
    然后,
    p
    将一直存在,直到
    somePromiseReturningFunction()
    使用它返回的承诺的任何引用(通常,但并不总是在承诺最终实现或拒绝时发生)以及变量
    p
    超出范围。如果
    p
    从未超出范围(比如它是全局的或在其他持久的范围内),那么它将永远保持不变(就像任何其他Javascript对象一样)


    你的问题中有一些误解,所以让我试着澄清一下

    你正在使用构造
    p=p.then(dosomething(x))这可能不正确。您需要传递函数引用。因此,除非您希望立即执行
    doSomething(x)
    ,并且它还返回另一个函数,即您希望调用的then
    .then()
    处理程序(在这里似乎不太可能),否则这不是正确的构造。你可能想要:

    p = p.then(result => dosomething(x));
    
    或者使用ES5语法:

    p = p.then(function(result) {
        return dosomething(x)
    });
    
    您在这方面也显示了相同的问题:

    return p.then(finalthing()).catch(pretendnobadthing());
    
    这可能是:

    return p.then(finalthing).catch(pretendnobadthing);
    
    请记住,当您使用
    f()
    时,这意味着要立即执行
    f
    。当您只传递
    f
    时,它传递一个函数引用,该函数引用