ホームページ  >  記事  >  ウェブフロントエンド  >  面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

php是最好的语言
php是最好的语言オリジナル
2018-08-01 10:52:341908ブラウズ

ES6 Promise の使用法は、面接や試験で常に共通のテストポイントです。Promise には all、reject、resolve などのよく知られたメソッドがあり、プロトタイプにも then や catch などのよく知られたメソッドがあります。

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

var p = new Promise(function(resolve, reject){
    //做一些异步操作
    setTimeout(function(){
        console.log('执行完成');
        resolve('随便什么数据');
    }, 2000);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

Promise のコンストラクターは、関数である 1 つのパラメーターを受け取り、2 つのパラメーター、resolve と拒否を渡します。これらはそれぞれ、非同期操作が正常に実行された後のコールバック関数と、非同期操作が正常に実行された後のコールバック関数を表します。非同期操作は失敗します。実際、標準に従って、ここで「成功」と「失敗」を使用するのは正確ではありません。resolve は Promise のステータスを fullfiled に設定し、reject は Promise のステータスを拒否に設定します。ただし、最初はこのように理解できます。概念については後で詳しく検討します。

上記のコードでは、setTimeout という非同期操作を実行し、2 秒後に「実行完了」が出力され、resolve メソッドが呼び出されます。

コードを実行すると2秒後に「実行完了」が出力されます。知らせ!新しいオブジェクトを作成しただけで、渡した関数はすでに実行されています。これは注意が必要な点です。したがって、Promise を使用するときは、通常、Promise を関数でラップし、次のように必要に応じてこの関数を実行します。

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

function runAsync(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('执行完成');
            resolve('随便什么数据');
        }, 2000);
    });
    return p;            
}
runAsync()

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

このとき、次の 2 つの質問があるはずです。 1. Promise の利点は何ですか?ウールのような機能をパッケージ化しますか? 2.resolve('任意のデータ'); これは乾いた髪ですか?

続けましょう。ラップされた関数の最後に Promise オブジェクトが返されます。つまり、この関数を実行すると Promise オブジェクトが取得されます。 Promise オブジェクトには then メソッドと catch メソッドがあることを思い出してください。これが威力です。以下のコードを見てください:

runAsync().then(function(data){
    console.log(data);
    //后面可以用传过来的数据做些其他操作
    //......
});

runAsync() の戻り時に then メソッドを直接呼び出し、関数であるパラメーターを受け取り、 runAsync でsolveを呼び出すときに渡されるパラメーターを取得します。このコードを実行すると、2 秒後に「実行が完了しました」と出力され、続いて「任意のデータ」が出力されます。

この時点で、この関数は通常のコールバック関数と同じであり、runAsync の非同期タスクが完了した後に実行できることがわかりました。これがPromiseの役割で、簡単に言うと本来のコールバックの書き方を分離し、非同期操作を実行した後にチェーン呼び出しでコールバック関数を実行することができます。

あなたは否定的かもしれませんが、これが素晴らしい Promise の機能なのですか?次のようにコールバック関数をカプセル化して runAsync に渡しても同じではないでしょうか:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

function runAsync(callback){
    setTimeout(function(){
        console.log('执行完成');
        callback('随便什么数据');
    }, 2000);
}

runAsync(function(data){
    console.log(data);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

効果は同じなので、なぜわざわざ Promise を使うのでしょうか?そこで問題は、コールバックの層が複数ある場合はどうすればよいかということです。コールバックも非同期操作であり、実行後に対応するコールバック関数が必要な場合はどうすればよいでしょうか?別の callback2 を定義してコールバックに渡すことはできません。 Promise の利点は、then メソッドで Promise オブジェクトを記述して返し、引き続き then を呼び出してコールバック操作を実行できることです。

チェーンオペレーションの使い方

このように、Promiseは表面的にはコールバックの記述を簡素化するだけですが、本質的にはPromiseの本質は「状態」であり、それを保持して送信することでコールバック関数を呼び出すことができます。これは、コールバック関数を渡すよりもはるかに簡単で柔軟です。したがって、Promise を使用するための正しいシナリオは次のとおりです:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return runAsync3();
})
.then(function(data){
    console.log(data);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

この方法では、各非同期コールバックのコンテンツを 2 秒ごとに順番に出力でき、runAsync2 で解決するために渡されたデータを次の Get で処理できます。 then メソッドからです。実行結果は次のとおりです。

3 つの関数 runAsync1、runAsync2、および runAsync3 がどのように定義されているか推測しますか?はい、こんな感じです

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

りー

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了,比如我们把上面的代码修改成这样:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return '直接返回数据';  //这里直接返回数据
})
.then(function(data){
    console.log(data);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

那么输出就变成了这样:

reject的用法

到这里,你应该对“Promise是什么玩意”有了最基本的了解。那么我们接着来看看ES6的Promise还有哪些功能。我们光用了resolve,还没用reject呢,它是做什么的呢?事实上,我们前面的例子都是只有“执行成功”的回调,还没有“失败”的情况,reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。看下面的代码。

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

function getNumber(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num);
            }
            else{
                reject(&#39;数字太大了&#39;);
            }
        }, 2000);
    });
    return p;            
}

getNumber()
.then(
    function(data){
        console.log(&#39;resolved&#39;);
        console.log(data);
    }, 
    function(reason, data){
        console.log(&#39;rejected&#39;);
        console.log(reason);
    }
);

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

getNumber函数用来异步获取一个数字,2秒后执行完成,如果数字小于等于5,我们认为是“成功”了,调用resolve修改Promise的状态。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。

运行getNumber并且在then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。所以我们能够分别拿到他们传过来的数据。多次运行这段代码,你会随机得到下面两种结果:

或者

catch的用法

我们知道Promise对象除了then方法,还有一个catch方法,它是做什么用的呢?其实它和then的第二个参数一样,用来指定reject的回调,用法是这样:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

getNumber()
.then(function(data){
    console.log(&#39;resolved&#39;);
    console.log(data);
})
.catch(function(reason){
    console.log(&#39;rejected&#39;);
    console.log(reason);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。请看下面的代码:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

getNumber()
.then(function(data){
    console.log(&#39;resolved&#39;);
    console.log(data);
    console.log(somedata); //此处的somedata未定义
})
.catch(function(reason){
    console.log(&#39;rejected&#39;);
    console.log(reason);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。但是在这里,会得到这样的结果:

也就是说进到catch方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能。

all的用法

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。我们仍旧使用上面定义好的runAsync1、runAsync2、runAsync3这三个函数,看下面的例子:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。所以上面代码的输出结果就是:

有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,是不是很酷?有一个场景是很适合用这个的,一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。

race的用法

all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,这个词本来就是赛跑的意思。race的用法与all一样,我们把上面runAsync1的延时改为1秒来看一下:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

这三个异步操作同样是并行执行的。结果你应该可以猜到,1秒后runAsync1已经执行完了,此时then里面的就执行了。结果是这样的:

你猜对了吗?不完全,是吧。在then里面的回调开始执行时,runAsync2()和runAsync3()并没有停止,仍旧再执行。于是再过1秒后,输出了他们结束的标志。

这个race有什么用呢?使用场景还是很多的,比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

//请求某个图片资源
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = &#39;xxxxxx&#39;;
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject(&#39;图片请求超时&#39;);
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方

requestImg函数会异步请求一张图片,我把地址写为"xxxxxx",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。运行结果如下:

相关文章:

详细解读JavaScript编程中的Promise使用_基础知识

JavaScript编程中的Promise使用大全_基础知识

相关视频:

Javascript - ES6实战视频课程

以上が面接や筆記試験で問われることの多いjsの基礎知識:ES6 Promiseの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。