无序承诺

时间:2016-10-25 16:31:58

标签: javascript coffeescript promise

鉴于以下code

p = () ->
  foo 5
  new Promise( (resolve, reject) ->
    console.log 'in promise'
    resolve 'done'
  )

foo = (n) ->
  console.log n
  if(n <= 0) then 0 else foo (n-1)

然后我称之为:

p().then (-> console.log 'hi'), (-> console.log 'there')

输出显示:

5
4
3
2
1
0
in promise
hi

首先,如果我希望p的整个身体出现在同一个Promise中,我是否必须将其包裹在new Promise ( (resolve, reject) ) -> ... )中?

其次,通过修改foohi5/4/3/2/1/0之前是否会打印in promise是否有可能?

最后,在then正文完全完成之前p()的成功案例会在哪些情况下完成?

1 个答案:

答案 0 :(得分:0)

  

首先,如果我希望整个p体出现在同一个Promise中,我必须将它包装在新的Promise中((解析,拒绝)) - &gt; ......)?

嗯,是的。如果你希望p的整个身体都在同一个承诺中发生,那么你必须将p的整个身体放在同一个承诺中。但是,正如Bergi在评论中提到的,这仍然不会影响您的整体代码行为。 Promise构造是一个同步过程,这意味着只要你创建一个Promise,它的体内代码就会运行。稍后发生的部分是承诺解决(成功或失败)。

p = () ->
  foo 5                             // happens synchronously
  new Promise( (resolve, reject) ->
    console.log 'in promise'        // happens synchronously
    resolve 'done'                  // happens asynchronously
  )

以下代码是等效的:

p = () -> 
  new Promise( (resolve, reject) ->
    foo 5                           // happens synchronously
    console.log 'in promise'        // happens synchronously
    resolve 'done'                  // happens asynchronously
  )

如果您提供更具体的用例,我可能会给出更具体的答案。

  

第二,通过修改foo,是否有可能在5/4/3/2/1/0之前或在承诺中打印?

Promise解析,根据规范,始终异步发生(在事件循环中以microtasks的形式)。这意味着所有同步代码(例如foo中的循环)必须在任何承诺解决方案发生之前完成。

引用Jake Archibald

  

Microtasks通常安排在当前正在执行的脚本之后发生的事情,例如对一批操作做出反应,或者在不承担全部新任务的情况下进行异步。只要没有其他JavaScript处于执行中期,并且在每个任务结束时,微调任务队列就会在回调后处理。在微任务期间排队的任何其他微任务都会添加到队列的末尾并进行处理。 Microtasks包括变异观察者回调,如上例所示,承诺回调。

因此,foo中的事情发生后p中发生事情的唯一方法是强制foo异步运行并在 {之后{1}}已完成。

解决此问题的一种方法是在p中解决Promise之后使用setTimeout来延迟foo的代码。这是因为p在事件循环的下一次迭代中调度常规任务,而微任务(因此Promises)被指定在事件循环的同一次迭代中运行。

这是一个JS演示:

注意:这可能不适用于所有浏览器。我在Chrome版本54.0.2840.71中测试了它。 Jake的文章提供了有关特定浏览器错误的更多详细信息。

setTimeout

  

最后,在p()主体完全完成之前,在哪种情况下会执行成功案例?

在任何情况下都不会因为const foo = (n) => { setTimeout(() => { console.log(n); if (n <= 0) { return 0; } else { return foo(n - 1); } }); } const p = () => { foo(5); return new Promise((resolve) => { console.log('in promise'); resolve('done'); }); } p().then(() => console.log('hi')); /* Output: in promise hi 5 4 3 2 1 0 */的成功案例取决于内部承诺。在我们调用p().then的Promise被解析(成功或失败)之前,无法调用传递到then的成功回调。

这是关于在编写JS框架时解决这些时序问题的another useful article