Do Promises只是让异步代码同步吗?为什么不使用同步代码?

时间:2016-06-22 02:12:28

标签: javascript node.js asynchronous promise synchronous

如果我做的事情如下:

let request = require('request');

function download(link) {
    return new Promise((resolve, reject) => {
        request.get(link).end((err, res) => {
            resolve(res);
        }); 
    });
}

let link = 'http://google.com';
download(link).then((res) => {
    //do stuff with res
});

为什么不同步等待请求返回?为什么甚至首先要承诺?

2 个答案:

答案 0 :(得分:3)

主要原因是,如果您要同步运行,则在处理同步请求时,所有Javascript都会被阻止。这可能会导致浏览器“冻结”#34;否则会导致糟糕的用户体验,因此最好避免使用。

虽然有一些exceptions,但典型的Javascript有single-threaded behavior

  

在处理任何其他消息之前,将完全处理每条消息。

因此,如果您有一个同步耗时的操作 - 等待AJAX​​响应,打开本地文件,甚至只是一个缓慢的计算 - 在操作完成之前不会运行任何Javascript。您的页面甚至可能会冻结,导致浏览器或操作系统提供杀死页面或应用程序。正如MDN关于synchronous XMLHttpRequests的文档所述,"由于对用户体验的负面影响,主线程上的同步请求已被弃用。"

自然地,即使存在上述所有缺陷,同步代码也更容易理解:

// BAD: This will block while each request takes place,
// regardless of whether that's 10 milliseconds or 10 seconds.
var number1 = getFirstNumberSynchronouslyFromServer(url1);
var number2 = getSecondNumberSynchronouslyFromServer(url2);
display(number1 * number2);

通过ES6,最简单的处理方法是使用回调方法:

getFirstNumberAsynchronously(url1, function(number1) {
  getSecondNumberAsynchronously(url2, function(number2) {
    display(number1 * number2);
  });
});

但是这很棘手,特别是在涉及错误处理时,特别是在尝试抽象出可能已经可用的值或者可能需要另一个耗时的请求或计算时。 ES6的承诺大部分都是为了解决这个问题:

var number1, number2;
getFirstNumberPromise().then(function(result) {
  number1 = result;
  return getSecondNumberPromise();
}).then(function(result) {
  number2 = result;
  return number1 * number2;
}).then(display).catch(handleError);

ES7的async / await完成了这项工作,使异步版本像同步版本一样易于阅读/理解:

var number1 = await getFirstNumberPromise();
var number2 = await getSecondNumberPromise();
display(number1 * number2);

(碰巧的是,以上所有示例都按顺序请求每个数字。使用Promises.all,在基于Promise的示例中并行执行此操作很容易,并且在嵌套中要复杂得多回调,同步或伪同步示例。)

答案 1 :(得分:0)

主要区别在于同步代码将阻塞下一个语句,但异步代码将阻止任何内容。

异步代码允许我们同时执行多个任务,但同步代码不会。

2个线程提供了很好的描述。阅读很好。