JavaScript 中的 Promise 跟异步有关系吗?还是我的理解有问题?谁能把 Promise 解释清楚? Promise 的正确用法应该是什么样的?

1 天前
 burnbrid

感觉 Promise 跟异步没有关系啊!我理解的异步是 ajax 这样的,ajax 将请求发出去之后,代码就继续往下执行了,等到 ajax 收到响应结果了,再回头执行 ajax 的回调函数,这才是异步。不是说你指定了回调函数就是异步。Promise 构造函数里面的代码是同步执行的,假如在 Promise 构造函数里面执行一个 10 万次的循环,主线程会等这 10 万次执行结束之后,才会继续执行下一行代码,这叫异步吗?异步跟回调函数没有一点关系。 异步就是不在主线程里面执行。

const ps = new Promise(function name(resolve, reject) { let i = 0; while(i<1000000){ i = i+1; console.log('i=',i); } }); console.log('promise 是异步吗?');

等上面这 100 万次循(最耗时的操作)环执行完,我还有必要通过 then 去指定回调函数吗?我直接执行回调函数就可以了,根本不需要通过 then 去执行回调函数。

2639 次点击
所在节点    JavaScript
46 条回复
cookii
1 天前
异步和并行是两个概念,单线程也可以异步。
chiaf
1 天前
把异步代码放进去

Promise 本身不是异步,他只是个对象,一个容器,用于封装和管理异步操作。

设计 Promise 不是为了解决回调地狱的问题吗?
iMusic
1 天前
我觉得 Promise 主要解决的是回调变成了链式。

关于你举例的这个问题,看下 JS 的事件循环机制,Promise 相关哪些是微任务。
ShadowPower
1 天前
Promise 不提供异步机制,而是管理异步流程
renmu
1 天前
promise 不是异步,异步的是网络请求,io 操作
Linho1219
1 天前
Promise 构造函数传进去的回调当然是直接同步执行的,但这个回调里面可以有网络请求,或者任何其他的“传统”的通过回调实现的异步操作,这些传统异步操作在成功或失败的时候调用 resolve reject ,实现异步代码执行结果的分发。
注意分发这个词。Promise 解决的是异步结果的分发问题,方便挂载回调而已,它本身只是一个容器。你可以将其理解为“大闸蟹券”,拿着券去领大闸蟹,但不意味着拿券和拿蟹是异步的(有螃蟹的时候也可以发券)。
因此 Promise 有两种使用方法:一种就是异步操作的 API 本身就是用 Promise 封装的,这样可以很方便地挂载回调;另一种是将传统的回调式 API 封装成 Promise ,这样可以更方便地挂载回调
yor1g
1 天前
promise 是回调的标准封装而已
Linho1219
1 天前
此外你的理解还有一个严重问题,异步回调还是在主线程中执行的,JS 是单线程的( worker 除外)。可以看看我写的这篇文章 https://notes.linho.cc/s?q=c876458647
ShadowPower
1 天前
另外,在不在主线程里执行并不能用来判断是不是异步。异步一般跟 IO 有关,主要用于解决线程会被 IO 阻塞的问题。
这里的 IO 可以是文件,可以是网络,也可以是用户的输入。
当然,也可以用多线程实现异步,但是并发不会很高。
june4
1 天前
你不看 resolve,reject 这二个参数吗,这是可以异步调用的,比如在用户事件回调/网络回调中,这就是异步啊。且你在 await 这个 promise 时会等到这二个参数被调用后才会往下执行,这又解决了回调地狱。
duanxianze
1 天前
Promise 本质就是语法糖
bsg1992
1 天前
异步 和并行不是一回事的
Promise 解决的函数回调回调地狱的问题
且 JS 本身单线程 靠的是 event loop 。
而你说的这个 是多线程, 在目前浏览器中 只有 worker 和网络请求是单独的线程执行的
panyang
1 天前
所实话,你的理解没有什么大问题。new Promise 中的代码确实是同步执行的,但是传入的 resolve 或 reject 函数会异步触发。

对于你的困惑,应该是你忘了 resolve 或 reject 函数会异步触发。
Linho1219
1 天前
@duanxianze Promise 哪里是语法糖???
luohechen
1 天前
@duanxianze async await 才是语法糖
PTLin
1 天前
你要明白 js runtime 的单线程 事件循环模型才能真正的了解 promise 和 js 的 async 。
搜索关键词:javascript 事件循环
leonshaw
1 天前
你最终要调用原生的异步方法才是异步
ns09005264
1 天前
我想 javascript 的异步大概是这样发展的:
1. 最开始是 xmlhttprequest ,然后通过回调函数处理异步结果。
2. 之后添加了 Promise ,通过链式调用来解决回调地狱,本质就是一个“工具类”,用户也可以手写 Promise ,在语法上没什么特别的。
3. 添加了 await 和 async 关键字,专门在语法层面改善了 Promise 的链式调用地狱。
现在的情况是,用来解决回调地狱的 Promise ,被 await 和 async 进一步取代了。


还能用到 Promise 的地方,这里有一个例子,有许多图片 node 共用一张精灵图,而图片 node 是根据用户滚动视图懒加载的,会先于精灵图的加载展示在页面文档里,因此利用了 Promise 给图片 node 一个保证,等你要展示图片的时候,再叫我。

https://github.com/MapoMagpie/eh-view-enhance/blob/d77e0655cff35818141b5e6e5246221b1fb12d74/src/platform/ehentai.ts#L211
在 211 行给 node.delaySrc 设置了 Promise 属性,但是在构造的时候将 Promise 里的 resolve 和 reject 拿走了,接着在 215 行的异步操作的回调函数里去执行 resolve 或 reject 。

最后在某个将来时刻再使用 node.delaySrc
https://github.com/MapoMagpie/eh-view-enhance/blob/d77e0655cff35818141b5e6e5246221b1fb12d74/src/img-node.ts#L146
iOCZS
1 天前
promise 是微任务队列,async&await 是协程
angrylid
1 天前
同步代码是逐行往下执行的,碰到网络请求必须等待结果,把后面的计算都阻塞了。
伪代码如下
```
var image = loadResourceSync('/assets/example.png')

canvas.draw(image) // 必须等待上一行得到结果才会往下执行
// 假设后面还有很多代码,都得等着这个网络请求
```
这样肯定是不合理的,除依赖这个图像资源的代码之外,其他的代码无须等待这个网络请求。
于是应该是
```
loadResource('/assets/example.png', (err, data) => {
// 这个函数会在网络请求完毕后调用
if(err) {
alert(err)
return
}
canvas.draw(data)
})

element.innerText = 'Hello World' // 此代码不会等待上面资源加载

```
但是这样很容易写出回调地狱,像这样
```
loadResource('/assets/example.png', (err, data) => {
loadResource('/assets/example2.png', (err, data) => {
loadResource('/assets/example3.png', (err, data) => {
// ...
})
})
})

```

Promise 是一个状态机,帮助你把回调地狱改造成链式调用。

大概像这样
```
var loadResource = (url) => new Promise((resolve, reject) => {
loadResource(url, (err, data) => { if(err) reject(err) else resolve(data) }
})

```
然后你就可以愉快地用链式地狱来替代回调地狱
```
loadResource('/assets/example.png')
.then((data) => {
// ...
return loadResource('/assets/example2.png')
})
.then((data) => {
// ...
return loadResource('/assets/example3.png')
})
```


不严谨地概括一下就是这样,有空你去看一下如何手搓 Promise ,代码其实并不多,就知道怎么回事了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1118623

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX