【问题标题】:How JavaScript promises work behind the scenesJavaScript Promise 如何在幕后工作
【发布时间】:2020-08-10 01:05:56
【问题描述】:

当 Promise 产生和消费时,我对幕后发生的事情感到非常困惑。请澄清我的观点,并为我的英语不好感到抱歉。

  1. 使用新关键字创建空白对象 Promise 构造函数是 调用和 new 关键字设置 Promise 构造函数指向的 this 空白对象 this = blankobject。
  2. Promise 构造函数在参数中接收回调(执行函数) 并调用执行器函数。
  3. 执行器函数接收两个回调 (resolve,reject) 作为参数
  4. setTimeout 在 executor 函数中被调用并且 setTimeOut 是 异步代码
  5. 异步代码进入后台,然后 Promise 构造函数返回 Promise 对象以前是空白对象和 Promise 对象引用 保存到 myPromise。
  6. 创建了一个变量

接下来会发生什么?当then方法被调用时then方法的代码进入后台?我想它会进入后台,变量是 console.log // 10

主代码执行完成后,异步代码启动setTimeout回调开始执行,执行完成后promise被满足,resolved函数返回值。这个值如何存储在 Promise 对象中,then 方法中发生了什么?

let myPromise = new Promise (
    (resolve, reject) => {

        setTimeout(() => {
            console.log(getIDs)
            resolve(10);

        }, 1500);

    }
)


let a = 10
        myPromise.then(val => {
            console.log(val);

        })
        console.log(a)

【问题讨论】:

  • 您可以在DOCUMENTATION找到所有这些问题的答案
  • 我想看看 then 方法对我们做了什么我看不到的,如果你用代码示例解释我,我很感激你
  • 简而言之,当你调用resolve(..)时,你传递给.then(..)的回调函数就会被执行。 myPromise 只是 Promise 的一个实例。它永远不会是空白的。至于进入后台,其工作原理取决于 JavaScript 引擎
  • 在正常执行中然后调用方法但是我传入的回调然后方法无法调用并且代码转到下一行并打印我在上面示例中显示的变量然后在promise解决后开始执行异步代码调用 then 方法中的回调告诉我我是否正确,并告诉我为什么我的问题得到 -1 我是 stackoverflow 的新手。
  • 相关:onetwothreefour

标签: javascript promise es6-promise


【解决方案1】:

我会按执行顺序浏览你的代码。

在任何时候this 的值都是它开始时的值。那是因为你只使用箭头函数。但这无关紧要,因为您没有引用 this

主要代码

let myPromise = new Promise(executor); 创建一个待处理的承诺对象。在创建 Promise 时,executor 函数将被执行。

setTimeout(callback, 1500);callback 函数放在某个内部定时器队列中。 javascript 引擎承诺在(至少)1500 毫秒后尽最大努力执行callback

let a = 10; 将变量a 设置为10

myPromise.then(onFulfilled); 创建另一个待处理的承诺。它与myPromise 相关联,因此onFulfilled 将在myPromise 完成时异步调度。

console.log(a); 打印出a 的值,即10

在接下来的 1500 毫秒内没有任何反应。然后callback 被执行。

setTimeout 的回调

console.log(getIDs); 打印 getIDs。从名字你可以猜到它是一个函数。所以像[Function: getIDs] 这样的东西会被打印出来。

resolve(10); 满足myPromise 并将其结果设置为10。由于 myPromised 现在已完成,onFulfilledanotherPromise 被异步调度。

现在我们必须等待调用堆栈处理。之后,onFulfilled 将被调用。

onFulfilled of myPromise.then

console.log(val); 打印val 的内容。也就是myPromise的结果。

【讨论】:

  • 执行器函数立即同步运行。
  • @BenAston 你是对的。回调也无权解决。现在..这让事情变得更加难以组织起来。
  • @BenAston 和 Robert 当程序运行到这一行时 let newPromise = myPromise.then(callback) 当主代码运行时是否调用了那里的方法?因为新的 promise 引用保存在 newPromise 变量中,所以我假设 then 方法在那里调用,它返回的 promise 引用保存在 newPromise 但附加的处理程序异步调用
  • @javascriptlover 给.then 的函数永远不会被立即调用。 .then 的全部意义在于等待 myPromise 解决。而且即使myPromise 已经实现,赋予.then 的函数仍将异步运行以确保一致性。
  • @Robert let newPromise = myPromise.then(callback) console.log (newPromise) // Promise 为什么它不是 undefined 以及 new Promise 引用如何存储在 newPromise 变量中。
【解决方案2】:

以下是内置Promise class的简化实现。 catchfinally 尚未实现。

提供给 Promise 构造函数的函数称为 executor 函数,并立即同步调用。

每个 Promise 都有一个方法 .then,启用 Promise 的链接。

提供给.then 的函数总是在微任务上异步调用(注意下面使用queueMicrotask)。

每次调用.then,都会创建并返回一个新的promise。

.then 可以在同一个 Promise 上多次调用,从而创建 Promise 结果的多播和 Promise 链的分支。

promise 可以处于以下三种状态之一:待处理、已完成或已拒绝。状态转换是单向的:您不能从已完成或已拒绝,回到待处理。

如果一个 Promise 被另一个 Promise 解决,那么两个 Promise 链会连接起来,并且外层 Promise 会采用内层 Promise 的状态(可能是待处理的),直到内层 Promise 解决。

function Promise(executor) {
  if (!executor) throw "Promise executor undefined"
  let status = "pending", value, thenQ = []

  const then = onFulfilled => {
    let resolver
    // This ensures control does not move to later promises 
    // until prior promises have been resolved.
    const nextPromise = new Promise(resolve => (resolver = resolve))
    // More than one "then" can be registered with each promise.
    thenQ.push((...args) => resolver(onFulfilled(...args)))
    return nextPromise
  }

  // We check if the result is a "thenable"; if so, we treat
  // it as an inner promise, otherwise we simply fulfil with 
  // the result.
  const resolve = result => result?.then ? result.then(fulfil) : fulfil(result)

  // When a promise has been fulfilled, its "thens" can be run.
  const fulfil = result => (status = "fulfilled", value = result, executeThens(value))

  // "Thens" are run asynchronously, on a microtask.
  const executeThens = value => queueMicrotask(() => thenQ.forEach(el => el(value)))

  // The executor is run synchronously.
  executor(resolve)

  return {
    then,
    get status() { return status },
    get value() { return value }
  }
}

// Chaining
new Promise(resolve => {
  console.log('Waiting for step 1...')
  setTimeout(() => resolve("One, two..."), 1500)
})
.then(result => new Promise(resolve => {
  console.log('Waiting for step 2...')
  setTimeout(() => resolve(`${result}three, four`), 1500)
}))
.then(result => console.log(`Chaining result: ${result}.`))

// Branching
const p = new Promise(resolve => {
  console.log('Waiting for step a...')
  setTimeout(() => resolve("Alpha, Bravo..."), 1500)
})

p.then(result => new Promise(resolve => {
  console.log('Waiting for step b1...')
  setTimeout(() => resolve(`${result}Charlie, Delta`), 1500)
})).then(console.log)

p.then(result => {
  console.log('Waiting for step b2...')
  return `${result}Echo, Foxtrot`
}).then(console.log)

also

【讨论】:

  • 我很难理解为什么pReturn 是必要的。改用thens.push(value => resolver(onFulfilled(value))) 有什么不同吗?
  • 绝妙的答案。
猜你喜欢
  • 1970-01-01
  • 2016-08-05
  • 2019-04-28
  • 1970-01-01
  • 2014-11-18
  • 2011-02-17
  • 2012-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多