You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done().
可问题就来了,就像文章里说的,为啥jquery 对于jsonp的实现不允许async: false呢,在上述片段理由一句话Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.,同不调用会阻塞browser的其他处理,而jsonp的实现是基于script标签实现的,就是因为这个么?不知道了,ok我们来继续, 我看到stackoverflow上有这么一段回答
It is completely impossible to do synchronous
JSONP. JSONP works by creating a <script> tag;
the browser does not expose any way to wait for
a <script> tag. In addition, SJAX is never a good idea; it will freeze the browser until the server replies.
You need to correctly use asynchrony. Consider using promises.
按照这段回答呢是说没办法,显然这是洪荒年代了,我来看看
文中提到的async属性caniuse 显然使用这个属性,我们是有办法的。我们再来看看文中提到的实现
export const loadJsonpSync = (url) => {
var result;
window.callback1 = (data) => (result = data)
let head = window.document.getElementsByTagName('head')[0];
let js = window.document.createElement('script');
js.setAttribute('type', 'text/javascript');
js.setAttribute('async', 'sync');
// 这句显式声明强调src不是按照异步方式调用的
js.setAttribute('src', url);
head.appendChild(js);
return result
}
function* g() {
yield var a = 123
yield console.log(a);
}
function g() {
let state = {
next: () => {
state.next = f1
}
}
function f1() {
var a = 123
state.next = f2
}
function f2() { console.log(a) } }
今天看了一篇很棒的文章似是而非的JS - 异步调用可以转化为同步调用吗?
里面讲解了很多知识点,写篇文章总结总结,其实所有所有的就是想把异步代码调用,串行化执行(async, promise, co,async/await等等方法,而这片文章就是讲讲里面到底是啥)
jquery ajax的async属性(对于我这种几乎不用jquery的
人来说完全不知道这是什么鬼,只能靠猜...),查阅文档,当async
设置为true时异步调用,设为false时,则是同步调用
可问题就来了,就像文章里说的,为啥jquery 对于jsonp的实现不允许async: false呢,在上述片段理由一句话
Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
,同不调用会阻塞browser的其他处理,而jsonp的实现是基于script标签实现的,就是因为这个么?不知道了,ok我们来继续, 我看到stackoverflow上有这么一段回答上面这段代码其实不难理解,主要是要设置script标签的
async属性为sync,
window.callback1 = (data) => (result = data)
这是个jsonp实现,callback1显然就是, 要执行的回调, 可是作者说拿到的却是undefined,解释一下为什么jsonp中的async没有生效,现在解释起来真的是相当轻松,即document.appendChild的动作是交由dom渲染线程完成的,所谓的async阻塞的是dom的解析(关于dom解析请大家参考webkit技术内幕第九章资源加载部分),而非js引擎的阻塞。实际上,在async获取资源后,与js引擎的交互依旧是push taskQueue的动作,也就是我们所说的async call, 就是说async其实是阻塞dom解析线程,而非js执行线程,这就意味着,dom渲染就不进行了,一直到script加载完成,而js线程没有被阻塞,所以在dom线程阻塞等待的时候,js线程已经在执行了就直接反回result,所以很明显是undefined
异步转同步实现(即只考虑如何实现异步转同步实现)
先看一段文中提到的异步与同步定义
(确定百度不会死人么2333333),还可以借助甘特图来表达一下

显然, t1,t2是同步,t1,t3是异步
作者提了一个实现例子
对于这段的解读,注释已经很详细了,这时候作者就继续追问了,那么js可以么?作者查看了,jquery,node的底层实现,都是使用的原生代码实现的,并没有使用js, 那么可以使用setTimeout来模拟fork么?
作者实现了第一个版本如下
显然这段代码,肯定是不行的,因为大家都知道,js是单线程的,一旦执行了while(lock)就不可能再执行其他代码了,setTimeout的执行也是由于事件循环的调度执行的,但执行体仍然是同一个线程,作者按照理论模拟实现了一个eventloop,关于这个话题可以在写篇文章,坐等吧
接下来我们继续改进我们上面的代码片段
作者说了,这是对while(true)做了切块处理(显然这又是可以讲解的一个话题),其实就是估计一下结束时间,不让while(true)阻塞了所有的代码,使用sleep估计一下运行时间,是有偏差的
可是,如果把代码最后的foo() 变成 foo() && console.log('wait5sdo'),显然wait5sdo依然没有在foo中的sleep执行完成以后在执行,是直接输出了,在js代码中,
========
同步执行代码必然是在异步代码之前执行的
=======所以,无论从理论还是实际出发,我们都不得不承认,在js中,把异步方法改成同步方法这个命题是水月镜花.
async&await
我去这段代码亲手推翻了==同步执行的代码片段必然在异步之前。== 的黄金定律!借助作者话就是意不意外,惊不惊喜,
相信很多人都会说,async/await是CO的语法糖,CO又是generator/promise的语法糖,好的,那我们不妨去掉这层语法糖,来看看这种代码的本质, 关于CO,读的人太多了,我实在不好老生常谈,可以看看这篇文章,咱们就直接绕过去了,这里给出一个简易的实现
http://www.cnblogs.com/jiasm/p/5800210.html
显然这里的yield是个黑魔法啊,其实我们完全可以使用cb,来实现一个generator,见下
接下来是作者原话了
到此我们就完成了generator到function的转换,,这段代码本身也解释清楚了generator的本质,高阶函数,片段生成器,或者直接叫做函数生成器
(这一部分有很多可以聊得,再聊)
就好比上面代码的转换过程,由于有变量提升的问题, generator中的console.log(a)是有输出的,而转换过后的是没有的,这就是其中作用域的坑
其实这个东西,如果把代码写出来估计大家都能看出问题来,可若是没有的话,会有点儿没注意这个代码的转换问题,我还以为是之前的转换代码本身有问题,其实是这种转换,本身对于js作用域的割裂(**************)
其实,在不知不觉中,我们已经重新发明了计算机科学中大名鼎鼎的CPS变换https://en.wikipedia.org/wiki/Continuation-passing_style
最后的最后,容我向大家介绍一下facebook的CPS自动变换工具--regenerator。他在我们的基础上修正了作用域的缺陷,让generator在es5的世界里自然优雅。我们向facebook脱帽致敬!!https://github.com/facebook/regenerator
The text was updated successfully, but these errors were encountered: