【问题标题】:Converting Callbacks Into Promise Syntax将回调转换为 Promise 语法
【发布时间】:2019-08-17 01:20:00
【问题描述】:

为了更好地理解 Promise 语法,我正在尝试将以下伪代码转换为现代 JavaScript。

这是旧代码,带有臭名昭著的回调地狱:

1995 JavaScript

var floppy = require( 'floppy' );

floppy.load( 'disk1', function( data1 ) {
    floppy.prompt( ' Please insert disk 2', function() {
        floppy.load( 'disk2', function( data2 ) {
            floppy.prompt( ' Please insert disk 3', function() {
                floppy.load( 'disk3', function( data3 ) {
                    floppy.prompt( 'Please insert disk 4', function() {
                        // If Node.js would've existed in 1995.
                    } );
                } );
            } );
        } );
    } );
} );

请帮我用 Promise 语法(无 async/await)将上面的内容转换成 JavaScript。我是 Promise 新手,但这就是我想出的。语法、嵌套和功能是否与上述代码相同?如果没有,请帮助我使用 Promises 将疯狂的回调转换为漂亮的 JavaScript。

更新代码

const floppy = require( 'floppy' );

floppy.load( 'disk1' )
.then( data1 => {
    floppy.prompt( 'Please insert disk 2' );
} )
.then(
    floppy.load( 'disk2' )
)
.then( data2 => {
    floppy.prompt( 'Please insert disk 3' );
} )
.then(
    floppy.load( 'disk3' )
)
.then( data3 => {
    floppy.prompt( 'Please insert disk 4' );
} )
.then(
    // Node.js using Promises avoids callback hell!
);

【问题讨论】:

  • 你可以在 1995 年实现 Promise。这只是一种设计模式。无需修改语言即可实现承诺

标签: javascript node.js promise callback


【解决方案1】:

首先使用以下方法对您的floppy 对象进行monkeypatch:

floppy.loadAsync = function(d) {
    return new Promise(resolve => {
        floppy.load(d, resolve);
    });
};
floppy.PromptAsync = function(message) {
    return new Promise(resolve => {
        floppy.load(message, resolve);
    });
};

现在你可以写了:

floppy.loadAsync('disk1')
.then(data1 => floppy.promptAsync(' Please insert disk 2'))
.then(() => floppy.loadAsync('disk2'))
.then(data2 => floppy.promptAsync(' Please insert disk 3'))
.then(() => floppy.loadAsync('disk3'))
.then(data3 => floppy.promptAsync(' Please insert disk 4'));

如果您想在最终回调中访问data1data2data3data4,那么您有一个range of options available to you

例如,使用“Break the Chain”方法,您可以这样写:

var promise1a = floppy.loadAsync('disk1');
var promise1b = promise1a.then((data1) => floppy.promptAsync(' Please insert disk 2'));

var promise2a = promise1b.then(() => floppy.loadAsync('disk2'));
var promise2b = promise2a.then((data2) => floppy.promptAsync(' Please insert disk 3'));

var promise3a = promise2b.then(() => floppy.loadAsync('disk3'));
var promise3b = promise3a.then((data3) => floppy.promptAsync(' Please insert disk 4'));

var promise4a = promise3b.then(() => floppy.loadAsync('disk4'));

Promise.all([promise1a, promise2a, promise3a, promise4a]).then((data) => {
    var data1 = data[0];
    var data2 = data[1];
    var data3 = data[2];
    var data4 = data[3];
});

【讨论】:

  • 谢谢兄弟!包含 .all() 示例的额外积分。 :-)
【解决方案2】:

异步会更干净。

编写一个包装函数,将回调语法转换为一个promise。

const bigFloppyLoad = disk => new Promise(done => floppy.load(disk1, done));

那我猜你也需要一个提示符...

const bigFloppyPrompt = message => new Promise(done => floppy.prompt(message, done));

然后您可以在 async 块中运行它们。

(async ()=>{
  const data1 = await bigFloppyLoad('disk1');
  await bigFloppyPrompt("Insert disk 2");
  const data2 = await bigFloppyLoad('disk2');
  await bigFloppyPrompt("Insert disk 3");
  // ... and so forth
})();

【讨论】:

  • 拜托,没有异步/等待所述。这是为了学习 Promise 语法。
  • @GTSJoe - 异步/等待 is 承诺。请注意转换器函数如何返回承诺。听起来你正试图对我的回答承担很大的软盘负担。
猜你喜欢
  • 2018-04-23
  • 2017-03-22
  • 2015-12-11
  • 2020-10-19
  • 2016-08-11
  • 2018-09-19
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
相关资源
最近更新 更多