JavaScript Promise 是异步的吗?

IT技术 javascript asynchronous promise
2021-02-27 05:31:57

只是一个简单的澄清问题: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可以使代码在 a 内非阻塞Promise吗?

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

2个回答

我认为你在误解下工作。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”之后)。

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

您的 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