【问题标题】:Are JavaScript Promise asynchronous?JavaScript Promise 是异步的吗?
【发布时间】:2016-08-03 23:32:40
【问题描述】:

只是一个简单的澄清问题:JavaScript Promise 是异步的吗?我已经阅读了很多关于Promise 和异步编程(即ajax 请求)的帖子。如果Promise 不是异步的,我们如何做到这一点?

例如,我有一个函数将函数f 与参数数组args 包装在Promise 中。 f 本质上没有什么是异步的。

function getPromise(f, args) {
 return new Promise(function(resolve, reject) {
  var result = f.apply(undefined, args);
  resolve(result);
 });
}

为了使这个异步,我阅读了一些 SO 帖子并决定 setTimeout 是很多人建议使代码非阻塞的。

function getPromise(f, args) {
 return new Promise(function(resolve, reject) {
  setTimeout(function() { 
   var r = f.apply(undefined, args);
   resolve(r);
  }, 0);
 });
}

这种带有setTimeout 的方法是否可以使Promise 内的代码非阻塞?

(请注意,我不依赖任何第三方 Promise API,仅依赖于浏览器支持的 API)。

【问题讨论】:

标签: javascript asynchronous promise


【解决方案1】:

我认为你在误解下工作。 JavaScript 代码总是*阻塞;那是因为它在单个线程上运行。 Javascript 中异步编码风格的优点是 I/O 等外部操作不需要阻塞该线程。处理来自 I/O 的响应的回调仍然处于阻塞状态,并且没有其他 JavaScript 可以同时运行。

* 除非您考虑运行多个进程(或浏览器上下文中的 WebWorkers)。

现在针对您的具体问题:

只是一个简单的澄清问题:JavaScript Promise 是异步的吗?

不,传递给 Promise 构造函数的回调会立即同步执行,尽管绝对有可能启动异步任务,例如超时或写入文件并等待异步任务完成后再解析 Promise ;事实上,这是 Promise 的主要用例。

这种带有 setTimeout 的方法是否可以使 Promise 中的代码非阻塞?

不,它所做的只是改变执行顺序。您的脚本的其余部分将一直执行到完成,然后当它没有其他内容可以执行 setTimeout 的回调时将被执行。

澄清:

    console.log( 'a' );
    
    new Promise( function ( ) {
        console.log( 'b' );
        setTimeout( function ( ) {
            console.log( 'D' );
        }, 0 );
    } );

    // Other synchronous stuff, that possibly takes a very long time to process
    
    console.log( 'c' );

上述程序确定性地打印:

a
b
c
D

这是因为 setTimeout 的回调直到主线程没有任何事情要做(在记录 'c' 之后)才会执行。

【讨论】:

  • 我现在明白了一点。我想(除非我向后弯腰并了解 WebWorkers),使用Promise 不会使我的代码成为非阻塞或aysnc。基本上,我将继续使用Promise,因为至少现在我没有嵌套回调处理。谢谢。
  • 我知道这个答案是不久前写的,但我很好奇是否有人对此有任何参考?根据 MDN,Promises 是异步的:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/….
  • 我也想弄清楚 Promise 是异步的还是同步的。看着 - developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/… '从本质上讲,promise 是一个返回的对象,您将回调附加到该对象,而不是将回调传递给函数。我知道 promise 本身是同步的,但是,它最常与异步函数一起使用。因此,有人说 - 'Promise 是一个对象,表示异步操作的最终完成或失败' 示例包括异步功能和普通功能。
【解决方案2】:

您的 MDN 参考资料很有帮助。谢谢。 如果你运行这个,你应该看到 异步输出。

================================================ ================== 使用“Promise”进行异步

const log = console.log;

//---------------------------------------

class PromiseLab {

    play_promise_chain(start) {
        //"then" returns a promise, so we can chain
        const promise = new Promise((resolve, reject) => {      
            resolve(start);
        });     
        promise.then((start) => {
            log(`Value: "${start}" -- adding one`);
            return start + 1;
        }).then((start) => {
            log(`Value: "${start}" -- adding two`);
            return start + 2;
        }).then((start) => {
            log(`Value: "${start}" -- adding three`);
            return start + 3;
        }).catch((error) => {
            if (error) log(error);
        });             
    }
        
}

//---------------------------------------

const lab = new PromiseLab();
lab.play_promise_chain(100);
lab.play_promise_chain(200);

输出应该是异步的,例如:

Value: "100" -- adding one
Value: "200" -- adding one
Value: "101" -- adding two
Value: "201" -- adding two
Value: "103" -- adding three
Value: "203" -- adding three

================================================ ================== 使用“MyPromise”同步(例如基本 js 代码)

const log = console.log;

//---------------------------------------

class MyPromise {
    
    value(value) { this.value = value; }
    
    error(err) { this.error = err; }
    
    constructor(twoArgFct) {
        twoArgFct(
            aValue => this.value(aValue),
            anError => this.error(anError));    
    }
    
    then(resultHandler) { 
        const result = resultHandler(this.value);
        return new MyPromise((resolve, reject) => {     
            resolve(result);
        });
    }
    
    catch(errorHandler) { 
        errorHandler(this.error());
    }
    
}

//--------------------------------------
    
class MyPromiseLab {

    play_promise_chain(start) {
        //"then" returns a promise, so we can chain
        const promise = new MyPromise((resolve, reject) => {        
            resolve(start);
        });     
        promise.then((start) => {
            log(`Value: "${start}" -- adding one`);
            return start + 1;
        }).then((start) => {
            log(`Value: "${start}" -- adding two`);
            return start + 2;
        }).then((start) => {
            log(`Value: "${start}" -- adding three`);
            return start + 3;
        }).catch((error) => {
            if (error) log(error);
        });             
    }
        
}

//---------------------------------------

const lab = new MyPromiseLab();
lab.play_promise_chain(100);
lab.play_promise_chain(200);

输出应该是同步的:

Value: "100" -- adding one
Value: "101" -- adding two
Value: "103" -- adding three
Value: "200" -- adding one
Value: "201" -- adding two
Value: "203" -- adding three

【讨论】:

    猜你喜欢
    • 2018-01-14
    • 2016-08-13
    • 2017-02-10
    • 2020-03-04
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 2015-07-09
    相关资源
    最近更新 更多