Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript a'的好处是什么;承诺';CommonJS中的抽象?_Javascript_Abstraction_Commonjs_Promise - Fatal编程技术网

Javascript a'的好处是什么;承诺';CommonJS中的抽象?

Javascript a'的好处是什么;承诺';CommonJS中的抽象?,javascript,abstraction,commonjs,promise,Javascript,Abstraction,Commonjs,Promise,我正在阅读,关于承诺抽象的部分对我来说似乎有点过于复杂。以下是一个例子: requestSomeData("http://example.com/foo") // returns a promise for the response .then(function(response){ // ‘then’ is used to provide a promise handler return JSON.parse(response.body); // parse the b

我正在阅读,关于承诺抽象的部分对我来说似乎有点过于复杂。以下是一个例子:

requestSomeData("http://example.com/foo") // returns a promise for the response
    .then(function(response){ // ‘then’ is used to provide a promise handler
        return JSON.parse(response.body); // parse the body
    }) // returns a promise for the parsed body
    .then(function(data){
        return data.price; // get the price
    }) // returns a promise for the price
    .then(function(price){ // print out the price when it is fulfilled
        print("The price is " + price);
    });
在我看来,以下几行代码可以提供相同的结果:

requestSomeData("http://example.com/foo")
    .requestHandler(function(response){
        // parse the body
        var data  = JSON.parse(response.body);

        // get the price
        var price = data.price;

        // print out the price
        print("The price is " + price);
    });

虽然两者最终都将完成相同的事情,但区别在于第二个示例不是异步的。例如,考虑如果<代码> JSON.PARSE(…)<代码>会发生什么,结果是一个非常昂贵的操作;你必须坚持到一切都结束,这可能并不总是你想要的


这就是承诺带给你的:将正确答案的计算推迟到更方便的时候的强大能力。顾名思义,这个结构“承诺”会在某个时刻给出结果,只是现在不一定。您可以阅读更多有关期货和承诺在更大范围内工作的信息,让我们将承诺示例与纯Javascript示例进行比较:

// First we need a convenience function for W3C's fiddly XMLHttpRequest.
// It works a little differently from the promise framework.  Instead of 
// returning a promise to which we can attach a handler later with .then(),
// the function accepts the handler function as an argument named 'callback'.

function requestSomeDataAndCall(url, callback) {
    var req = new XMLHttpRequest();
    req.onreadystatechange = resHandler;
    req.open("GET", url, false);
    req.send();
    function resHandler() {
        if (this.readyState==4 && this.status==200) {
            callback(this);
        } else {
            // todo: Handle error.
        }
    }
}

requestSomeDataAndCall("http://example.com/foo", function(res){
    setTimeout(function(){
        var data = JSON.parse(res.responseText);
        setTimeout(function(){
            var price = data.price;
            setTimeout(function(){
                print("The price is "+price);
            },10);
        },10);
    },10);
});
正如Norbert Hartl指出的那样,JSON.parse()将挂起浏览器以查找大字符串。因此,我使用setTimeout()延迟它的执行(暂停10毫秒后)。这是Kris Kowal解决方案的一个例子。它允许当前Javascript线程完成,在回调运行之前释放浏览器以显示DOM更改并为用户滚动页面

我希望commonjs promise框架也使用setTimeout之类的东西,否则本文示例中后面的承诺将确实像人们担心的那样同步运行

我上面的替代方案看起来很难看,后面的过程需要进一步缩进。我重组了代码,以便我们可以在一个级别提供我们的流程链:

function makeResolver(chain) {
    function climbChain(input) {
        var fn = chain.shift();      // This particular implementation
        setTimeout(function(){       // alters the chain array.
            var output = fn(input);
            if (chain.length>0) {
                climbChain(output);
            }
        },10);
    }
    return climbChain;
}

var processChain = [
    function(response){
        return JSON.parse(response.body);
    },
    function(data){
        return data.price; // get the price
    },
    function(price){
      print("The price is " + price);
    }
];

var climber = makeResolver(promiseChain);
requestSomeDataAndCall("http://example.com/foo", climber);

我希望证明Javascript中传统的回调前向传递与承诺几乎是等价的。然而,经过两次尝试之后,我似乎已经展示了,关于原始示例中代码的整洁性,承诺是一个更加优雅的解决方案

我们还可以补充一点,第一个版本比第二个版本的优点是,它将细化链中的不同操作分离开来(函数也不必编写到位)。第二个版本混合了低级解析和应用程序逻辑。具体来说,第二个版本以坚实的原则为指导,违反了和

第二个代码段容易受到拒绝服务攻击,因为example.com/foo只会返回无效的json以使服务器崩溃。即使是空响应也是无效的JSON(尽管是有效的JS)。这就像是带有明显SQL注入漏洞的
mysql.*
示例

承诺代码也可以改进很多。这些是平等的:

requestSomeData("http://example.com/foo") // returns a promise for the response
    .then(function(response){ // ‘then’ is used to provide a promise handler
        // parse the body
        var data  = JSON.parse(response.body);

        // get the price
        var price = data.price;

        // print out the price
        print("The price is " + price);
    });
以及:

如果我们想要处理错误,那么它们是相等的:

requestSomeData("http://example.com/foo") // returns a promise for the response
    .then(function(response){ // ‘then’ is used to provide a promise handler
        // parse the body
        var data  = JSON.parse(response.body);

        // get the price
        var price = data.price;

        // print out the price
        print("The price is " + price);
    }).catch(SyntaxError, function(e) {
        console.error(e);
    });
以及:


这里什么时候方便?如果操作非常昂贵,并且JSON.parse是一段javascript代码,那么它无论如何都会挂起。不同之处在于,有了这个承诺,您就可以完成实际运行的函数。确实,无论是同步计算还是异步计算,解析都将花费相同的时间。但是,如果您花时间以这样一种方式来实现解析器,即在完成一小段操作后,它可以预期地向事件循环屈服,那么其他异步代码可以在每个块之间异步运行。这会使应用程序更具响应性,而不是更快。或者,JSON.parse可以是本机方法并在另一个方法上执行thread@Jan这没有帮助。JSON.parse已经是一个本机方法。这更适合未来阅读您的评论的人。您可以创建一个调用本机JSON.parse的web工作程序,以防止UI线程挂起。这将涉及加载新的worker,为新消息附加侦听器,在worker中调用JSON.parse,发布worker的结果,然后将结果传递给需要它的原始代码。将此代码包装在promise中可以抽象流程,并且可以更轻松地编码/重构/读取代码,而无需调试混乱。您是对的,将promise用于同步操作没有任何意义。因此,结果应该是相等的。但这是一个例子,说明了承诺的用法。对于在您的示例之后运行的代码,确实存在差异。如果您需要在示例之后运行一些东西,那么您可以(通过使用promise方法)在不知道示例代码正在做什么的情况下运行它
requestSomeData("http://example.com/foo") // returns a promise for the response
    .then(function(response){ // ‘then’ is used to provide a promise handler
        // parse the body
        var data  = JSON.parse(response.body);

        // get the price
        var price = data.price;

        // print out the price
        print("The price is " + price);
    }).catch(SyntaxError, function(e) {
        console.error(e);
    });
requestSomeData("http://example.com/foo")
    .requestHandler(function(response){
        try {
            var data = JSON.parse(response.body);
        }
        catch(e) {
            //If the above had a typo like `respons.body`
            //then without this check the ReferenceError would be swallowed
            //so this check is kept to have as close equality as possible with
            //the promise code
            if(e instanceof SyntaxError) {
                console.error(e);
                return;
            }
            else {
                throw e;
            }
        }

        // get the price
        var price = data.price;

        // print out the price
        print("The price is " + price);
    });