Mô-đun xác định ẩn danh () không khớp


129

Tôi gặp lỗi này khi duyệt webapp lần đầu tiên (thường là trong trình duyệt có bộ đệm bị vô hiệu hóa).

Lỗi: mô-đun xác định ẩn danh () mô-đun ẩn: hàm (yêu cầu) {

HTML :

<html>
   .
   .
   .
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
   <script> var require = { urlArgs: "v=0.4.1.32" }; </script>
   <script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
   <script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
   </body>
</html>

JS :

$(function () {
    define(function (require) {
        // do something
    });
});

Bất cứ ai cũng biết chính xác lỗi này có nghĩa là gì và tại sao nó xảy ra?

tập tin nguồn , một cuộc thảo luận ngắn về nó trong trang vấn đề github

Câu trả lời:


142

Giống như AlienWebguy đã nói, theo các tài liệu, allow.js có thể nổ tung nếu

  • Bạn có một định nghĩa ẩn danh (" các mô-đun gọi xác định () không có ID chuỗi ") trong thẻ tập lệnh riêng của nó (tôi giả sử thực sự chúng có nghĩa là bất cứ nơi nào trong phạm vi toàn cầu)
  • Bạn có các mô-đun có tên xung đột
  • Bạn sử dụng trình cắm trình tải hoặc mô-đun ẩn danh nhưng không sử dụng trình tối ưu hóa của.j.j để đóng gói chúng

Tôi đã gặp vấn đề này trong khi bao gồm các gói được xây dựng với browserify cùng với các mô-đun request.js. Giải pháp là một trong hai:

A. tải các gói độc lập không có yêu cầu trong các thẻ script trước khi tệp.j.j được tải hoặc

B. tải chúng bằng cách sử dụng allow.js (thay vì thẻ script)


2
tên xung đột là một tên phổ biến
Julio Marins

1
Một giải pháp khả thi khác, trong một số trường hợp đặc biệt với các mô-đun ẩn danh là ghi đè hàm notifyjs.onError để ngăn chặn ngoại lệ lỗi mặc định được ném bởi các hàmjjj ngăn chặn các mô-đun hoặc mã thành công được thực thi.
xtrm

1
Chỉ cần thêm một yêu cầu kéo ( github.com/requirejs/requirejs/pull/1763 ) để thư giãn trường hợp chính xác đó. Tôi nghĩ rằng nó là một vấn đề rất phổ biến những ngày này.
Bob S

1
Cảm ơn đã nói với tôi để tải chúng trước! Tôi không biết tại sao mẹo này không có trong tài liệu của chính mình ... Đó là nơi ngăn xếp có ích
Tobias Feil

14

Tôi đã gặp lỗi này vì tôi đã bao gồm tệp requestjs cùng với các librairies khác được bao gồm trực tiếp trong thẻ script. Những lời nói dối đó (như lodash) đã sử dụng một hàm xác định mâu thuẫn với định nghĩa của request. Tệp Yêu cầu đang tải không đồng bộ nên tôi nghi ngờ rằng định nghĩa của yêu cầu được xác định sau khi các thư viện khác xác định, do đó xung đột.

Để loại bỏ lỗi, bao gồm tất cả các tệp js khác của bạn bằng cách sử dụng các yêu cầu.


Hóa ra rất nhiều thư viện làm một việc như vậy, hoặc ít nhất là sử dụng / xuất một hàm như vậy. Tôi sẽ khuyên mọi người - nếu họ sử dụng yêu cầu - nhập mọi thứ có yêu cầu :)
Andrey Popov

12

Khi bắt đầu với Reacjs, tôi đã gặp phải vấn đề này và khi mới bắt đầu, các tài liệu cũng có thể được viết bằng tiếng Hy Lạp.

Vấn đề tôi gặp phải là hầu hết các ví dụ về người mới bắt đầu sử dụng "định nghĩa ẩn danh" khi bạn nên sử dụng "chuỗi id".

định nghĩa ẩn danh

define(function() {
        return { helloWorld: function() { console.log('hello world!') } };
 })


define(function() {
        return { helloWorld2: function() { console.log('hello world again!') } };
 })

xác định với id chuỗi

define('moduleOne',function() {
    return { helloWorld: function() { console.log('hello world!') } };
})

 define('moduleTwo', function() {
      return { helloWorld2: function() { console.log('hello world again!') } };
})

Khi bạn sử dụng định nghĩa với id chuỗi thì bạn sẽ tránh được lỗi này khi bạn cố gắng sử dụng các mô-đun như vậy:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});

(Chỉ cần một lưu ý cho hậu thế) Có được một số nhược điểm để tiếp cận này, được mô tả trong tài liệu : “xác định () cuộc gọi bao gồm tên cho mô-đun ... thường được tạo ra bởi các công cụ tối ưu hóa ... nam [ing] module chính mình ... làm cho Các mô-đun ít di động, thông thường tốt nhất là tránh mã hóa tên của mô-đun và chỉ để công cụ tối ưu hóa ghi vào tên mô-đun. Cũng như trong chủ đề GitHub này . Đây dường như là lý do tại sao việc liệt kê tên được loại trừ trong các ví dụ mới bắt đầu.
Đánh dấu G.

10

Theo các tài liệu :

Nếu bạn tự mã hóa thẻ script trong HTML để tải tập lệnh bằng lệnh gọi xác định ẩn danh (), lỗi này có thể xảy ra.

Cũng thấy nếu bạn tự mã hóa thẻ script trong HTML để tải tập lệnh có một vài mô-đun được đặt tên, nhưng sau đó thử tải một mô-đun ẩn danh cuối cùng có cùng tên với một trong các mô-đun được đặt tên trong tập lệnh được tải bằng tay mã script được mã hóa.

Cuối cùng, nếu bạn sử dụng trình cắm trình tải hoặc mô-đun ẩn danh (mô-đun gọi xác định () không có ID chuỗi) nhưng không sử dụng trình tối ưu hóa RequireJS để kết hợp các tệp với nhau, lỗi này có thể xảy ra. Trình tối ưu hóa biết cách đặt tên chính xác cho các mô-đun ẩn danh để có thể kết hợp chúng với các mô-đun khác trong một tệp được tối ưu hóa.

Để tránh lỗi:

  • Đảm bảo tải tất cả các tập lệnh gọi định nghĩa () thông qua API RequireJS. Không tự mã hóa các thẻ script trong HTML để tải các tập lệnh có các lệnh xác định () trong chúng.

  • Nếu bạn tự mã hóa thẻ script HTML, hãy chắc chắn rằng nó chỉ bao gồm các mô-đun được đặt tên và mô-đun ẩn danh sẽ có cùng tên với một trong các mô-đun trong tệp đó không được tải.

  • Nếu vấn đề là việc sử dụng plugin trình tải hoặc mô-đun ẩn danh nhưng trình tối ưu hóa RequireJS không được sử dụng để đóng gói tệp, hãy sử dụng trình tối ưu hóa RequireJS.


3
Đây có phải là một mô-đun được xác định ẩn danh? github.com/requirejs/example-multipage/blob/master/www/js/app/ Kẻ
đèn đường

5

Xin lưu ý rằng một số tiện ích mở rộng trình duyệt có thể thêm mã vào các trang. Trong trường hợp của tôi, tôi đã có một plugin "Emmet in all textareas" gây rối với các yêu cầu của tôi. Đảm bảo rằng không có mã bổ sung nào được thêm vào tài liệu của bạn bằng cách kiểm tra nó trong trình duyệt.


5

Các câu trả lời hiện có giải thích rõ vấn đề nhưng nếu bao gồm các tệp tập lệnh của bạn sử dụng hoặc trước requestJS không phải là một lựa chọn dễ dàng do mã kế thừa, một cách giải quyết hơi khó hiểu là xóa yêu cầu khỏi phạm vi cửa sổ trước thẻ script của bạn và sau đó khôi phục lại mật khẩu. Trong dự án của chúng tôi, điều này được gói gọn sau một lệnh gọi chức năng phía máy chủ nhưng hiệu quả trình duyệt sẽ thấy như sau:

    <script>
        window.__define = window.define;
        window.__require = window.require;
        window.define = undefined;
        window.require = undefined;
    </script>
    <script src="your-script-file.js"></script>        
    <script>
        window.define = window.__define;
        window.require = window.__require;
        window.__define = undefined;
        window.__require = undefined;
    </script>

Không phải là gọn gàng nhất nhưng dường như làm việc và đã tiết kiệm rất nhiều khúc xạ.


5
Trên thực tế đừng bao giờ làm điều này. Nó không hoạt động đúng trong IE.
jcbdrn

2
Không liên tục trong IE, các tập lệnh được bao gồm với requestJS sẽ xác định thiếu từ phạm vi cửa sổ của chúng ngay cả khi lệnh yêu cầu xuất hiện sau khi các biến đó được khôi phục. Chúng tôi không bao giờ quản lý để tìm ra lý do tại sao điều này xảy ra vì vậy chúng tôi đã từ bỏ giải pháp hacky này.
jcbdrn

2
@jcbdrn Không chỉ trên IE. Tôi đã thấy nó xảy ra trên nền tảng khác. Lý do là thông số HTML cung cấp các đảm bảo về thứ tự thực hiện các tập lệnh đồng bộ nhưng chỉ liên quan đến các tập lệnh đồng bộ khác . Nó không đảm bảo việc thực thi các tập lệnh không đồng bộ so với tập lệnh đồng bộ (hoặc ngược lại). Vì vậy, trong đoạn mã hiển thị trong câu trả lời ở đây, có thể có một tập lệnh không đồng bộ thực thi giữa hai scriptphần tử bất kỳ .
Louis

Nếu bạn có khả năng chỉnh sửa gói js bạn đang nhập, bạn chỉ có thể gói toàn bộ nội dung như sau:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne

2

Hoặc bạn có thể sử dụng phương pháp này.

  • Thêm allow.js trong cơ sở mã của bạn
  • sau đó tải tập lệnh của bạn thông qua mã đó

<script data-main="js/app.js" src="js/require.js"></script>

Những gì nó sẽ làm, nó sẽ tải tập lệnh của bạn sau khi tải request.js .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.