感觉 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 去执行回调函数。

举报· 3316 次点击
登录 注册 站外分享
31 条回复  
nsjs 初学 前天 18:03
通过你描述问题的过程,可以看出来你犯的错误是复合型的……不是一句话就能给你讲清楚的。 异步与同步,协程、线程与进程,动态语言的函数对象,js 的微队列和宏队列,这些你都得看一遍。
nsjs 初学 前天 17:54
1. 你被语法给迷惑了,then 和 Promise 在功能上基本是等价的,只是写法不一样 2. 你的示例代码有问题,你用不用 Promise 都会卡死,你需要了解一下 js 的微队列和宏队列 3. CPU 密集型作业,最佳解决方案应该是用多线程什么的,而不是你的示例代码的方法(虽然也写错了,但我知道你是想把这种任务分担到 CPU 空闲时做,而不卡死页面)
2218431632 初学 前天 17:21
promise 是解决回调地狱问题啊,promise 你可以塞同步任务,也可以塞异步任务。如果出现 cpu 密集型计算,可以用 worker 解决
charlie21 小成 前天 17:04
何为“异步编程“?系列三:等待未来 https://zhuanlan.zhihu.com/p/65551936
buffzty 小成 前天 16:57
正确用法: // 比如一个 api 需要查 2 次数据库 再进行某个操作 一般就这样写 const fn1 = async () => { console.log(1); return 1 };// 一个异步操作 const fn2 = async () => { console.log(2); return 2 };// 一个异步操作 const fn3 = async (a, b) => { console.log(3); return a + b };// 一个操作 异不异步都无所谓 反正都是最后一个操作了 console.log("begin") const task0 = new Promise((s, j) => { (async () => { try { const task1 = fn1() const task2 = fn2() const res1 = await task1 const res2 = await task2 s(await fn3(res1, res2)) } catch (e) { j(e) } })(); }) task0.then(res => { console.log("res:", res) }).catch(e => { console.error(e) }) console.log("end") // async 是 new Promise()的语法糖 // await 是 task.then 的语法糖 // return 是 resolve()的语法糖 // 现在一般都用 async 代替 Promise 可以少写几个字母
yazinnnn0 小成 前天 16:49
Promise 借鉴了 Monad 的一些设计思想, 用 CPS 变换优化实现链式组合异步操作(解决异步的回调地狱) async await 是类似于 Monad Comprehensions 的语法糖实现, 不过运行机制不一样, async await 依赖 javascript 运行时模型 原有的异步调用代码 asyncOp1((result1) => { asyncOp2(result1, (result2) => { asyncOp3(result2, (result3) => { /* ... */ }); }); }); Promise 优化之后的代码 asyncOp1() .then((result1) => asyncOp2(result1)) .then((result2) => asyncOp3(result2)) .then((result3) => { /* ... */ }); 使用 Monad Comprehensions 语法糖将中间变量从回调中取出来 result1 = await asyncOp1() result2 = await asyncOp2(result1) result3 = await asyncOp3(result2) 题外话, promise 不是标准的 monad, 但是有很多 monad 的特性, 比如统一的异常处理 (async await 之后就可以异步 try catch 了), 不然的话你想想每个回调都传一个 reject 参数来处理异常 (人肉 if err != nil 是吧) 所以说那些 go boy 用 if err != nil 来嘲笑 try catch 就挺逆天的, 学术界用几十年的时间来消除 errcode, 然后这玩意儿在 go boy 嘴里成最优雅的语言了😅 题外话 2, 其他语言的 Monad Comprehensions 语法糖举例 haskell compute :: Maybe Int compute = do x <- Just 3 y <- Just 5 return (x + y) -- 结果为 Just 8 csharp var query = from x in new[] { 1, 2 } from y in new[] { 3, 4 } select x + y; // 结果为 { 4, 5, 5, 6 } fsharp let asyncExample = async { let! x = async { return 3 } let! y = async { return 5 } return x + y } scala val compute: Option[Int] = for { x <- Some(3) y <- Some(5) } yield x + y swift func compute() async -> Int { let x = await fetchData() let y = await processData(x) return y } kotlin suspend fun compute(): Int { val x = async { fetchData() } val y = async { processData(x.await()) } return y.await() } java 没有😅 go 没有😅 rust 没有语法糖, 有个?(操作符)可以模拟类似功能(result option) 基本上后来兴起的工程向的语言都给异步相关的 api 实现了 monad comprehension, 一部分语言(fsharp kotlin 啥的)可以自定义语法 题外话 3 貌似一些 lisp people 极度反感 monad (和 go boy 殊途同归了属于是), clojure 社区里贴大字报明确反对标准库里添加 monad 实现, 吵了好几十条😅
musi 初学 前天 16:37
“我理解的异步是 ajax 这样的,ajax 将请求发出去之后,代码就继续往下执行了,等到 ajax 收到响应结果了,再回头执行 ajax 的回调函数,这才是异步。” “假如在 Promise 构造函数里面执行一个 10 万次的循环,主线程会等这 10 万次执行结束之后,才会继续执行下一行代码” 你不觉得你这两个就不是一个场景吗? ajax 在请求发出后只需要等待响应就可以了,这时候 CPU 是空闲的,你这 10 万次循环可是会一直占用 CPU 的。 你学 js 的时候不应该首先学 js 是单线程的么,在单线程中循环 10 万次的计算就是会造成卡顿,就算是天王老子来了这也没有任何优化的办法,直到后面出现了 web worker 我觉得你是没搞清楚异步和线程的概念,js 是通过事件循环机制实现的异步,简单的就是上面的 ajax 场景,发出一个请求后 cpu 进入空闲状态,可以做其他任务,当收到响应时通过事件告知 js 这个 ajax 任务完成了,你可以将 cpu 切换到这里继续做 ajax 之后的任务了。而 promise 就是提供了一套规范让开发者更方便使用这套机制而已,楼上说的语法糖在一定程度上也没错,毕竟在 promise 出现之前异步早就在 js 中被深度使用了
UnluckyNinja 初学 前天 16:27
感觉你是把异步同步和阻塞非阻塞搞混了,异步≠非阻塞,不要纠结于文字,理解 js 自身依赖于一个单线程的内置事件循环,通过将回调放入事件队列来实现异步操作。 部分 API 间接调用了底层代码,例如网络和 IO ,所以是真·非阻塞调用没问题,而你自己写的代码在同一个线程里运行所以是阻塞的,想要非阻塞代码可以写在 worker 里,这个流程也完全可以放在 promise 里。 promise 自身就是一个威力加强版回调工具,后面还有了 async await 进一步简化,没必要去纠结概念上的问题
buffzty 小成 前天 16:24
js 中的异步操作是 io,setTimeout,setInterval,Promise.proto.then ... 这些 js 的执行逻辑是先执行主线程代码,再执行任务队列中的函数,因为主线程代码会有一些异步操作,遇到就将这个异步操作的回调函数加入任务队列中 new Promise()不是异步操作,Promise.proto.then 才是异步 Promise 一般是去包住异步操作,让代码不变成回调地狱的,你 Promise 中根本没有异步操作 所以不必包一层. 如果想实现你想要的效果可以这样: new Promise(s => s()).then(_ => { let i = 0; while (i < 10) { i++; console.log('i=', i); } } ) console.log('promise 是异步吗?');
1234下一页
返回顶部